In regelmäßigen Abstand Funktion aufrufen
-
ten schrieb:
rüdiger schrieb:
meinste er hat bsd?
Ist POSIX und nicht BSD spezifisch.
-
Wenn ich das so lese ... so handelt es sich dabei min. um den sekundenbereich ... ich wollte jedoch in den millisekundenbereich ... gibt es vergleichbare funktionen für sowas?
Ich wäre über eine kleine erläuterung zur Funktionsweise der Funktion die dass kann sehr dankbar!
MfG
-
setitimer arbeitet mit struct timeval
struct timeval { long tv_sec; /* seconds */ long tv_usec; /* and microseconds */ };
-
Es wäre supi nett, wenn du mir mal eine simple beispiel implimentation schreiben kannst ...
Danke!
-
@Thomas_:
Du kannst dafür einfach 2 Threads nehmen. Thread 1 macht was auch immer du "solange Zeit ist" nebenbei machen willst (Funktion (2)), und hat z.B. Priorität 0. Thread 2 hat Priorität 1, und ruft in den Abständen wie du das möchtest eben diese Funktion (1) auf.
Dazu holst du dir einfach in Thread 2 aktuelle Zeit, und rufst Funktion (1) auf. Nachdem Funktion (1) fertig ist holst du dir wieder die aktuelle Zeit, rechnest aus wie lange es noch bis zum nächsten Aufruf von Funktion (1) dauern sollte, und legst den Thread einfach solange schlafen.
Unter Windows würde das inetwa so aussehen:
unsigned Thread2() { ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); DWORD interval = 123; // in milliseconds DWORD t0, t1; t1 = ::GetTickCount(); while (1) { t0 = t1; Funktion1(); t1 = ::GetTickCount(); DWORD diff = t1 - t0; if (diff < interval) Sleep(interval - diff); } } int main() { _beginthreadex(..., Thread2, ...); while (1) Funktion2(); }Die Genauigkeit von Sleep() und GetTickCount() liegt dabei üblicherweise bei etwa 15 ms. Wenns genauer sein soll musst du timeGetTime() statt GetTickCount() verwenden, und die Genauigkeit von timeGetTime() mittels timeBeginPeriod() einstellen. Wenns genauer als 1-2 ms sein soll... wirst du mit Windows nicht weit kommen.
Viel einfacher wäre es natürlich wenn ein Aufruf von Funktion2() niemals länger als 1-2 ms dauert, dann kannst du natürlich auf den Thread ganz verzichten, und statt Sleep() einfach immer solange Funktion2() aufrufen bis es wieder Zeit ist Funktion1() aufzurufen.
-
Hat er das os, für das wir ihm code schreiben?
-
edit: mist geschrieben und gelöscht

-
Bitte lacht mich nicht aus! was ist den ein os ... is das nicht ein Betriebssystem ... Windows? Ich habe Windows! Der Beispiel Code funzt supi! 1000 Dank dafür.
Den Teil mit timeBeginPeriod() habe ich nicht verstanden. Sleep(1) dauert bei mir auch nur etwas länger als eine ms (ca. 1.4). wirkt sich timeBeginPeriod() einmal angewendet die ganze Zeit auf die Application aus ... oder nur dort, wo sie aufgerufen wird. (ist sie, wenn ich sie aufrufe auch woanders noch geändert)?
Und ich habe noch ein kleines Problem. Wie kann ich verhindern, dass wenn ich in Funktion 2 nicht genau an einer kritischen Stelle stehn bleibe, damit Funktion 1 ausgeführt werden kann, die ihrerseits auf den gleichen Inhalt des kritischen Bereichs in Funktion 2 zugreift (also beide auf die gleichen Daten). Nun wurden Daten gelöscht, aber noch nicht NULL terminiert, so dass sie auf irgendwas zeigen ... wie kann ich verhindern, dass Funktion in so einen kritischen Bereich dran kommt? Also nich 1 ms warten muss?
Ich hoffe ihr erfasst das Problem, welches ich versuche zu beschreiben.
Vielen Dank!
-
Thomas_ schrieb:
Und ich habe noch ein kleines Problem. Wie kann ich verhindern, dass wenn ich in Funktion 2 nicht genau an einer kritischen Stelle stehn bleibe, damit Funktion 1 ausgeführt werden kann, die ihrerseits auf den gleichen Inhalt des kritischen Bereichs in Funktion 2 zugreift (also beide auf die gleichen Daten). Nun wurden Daten gelöscht, aber noch nicht NULL terminiert, so dass sie auf irgendwas zeigen ... wie kann ich verhindern, dass Funktion in so einen kritischen Bereich dran kommt? Also nich 1 ms warten muss?
Da Windows kein Echtzeitbetriebssystem ist, kannst du dich nicht darauf verlassen, dass eine Funktion alle n Millisekunden aufgerufen wird. Du kannst nur hoffen, dass das im Mittel ungefähr passt. Das Betriebssystem darf aber deine Funktionen beliebig hinauszögern, egal welche Timer du wählst.
Dein Problem des gegenseitigen Ausschlusses lässt sich am einfachsten mit "critical sections" lösen. Such mal in der Windows-SDK-Doku nach "CreateCriticalSection", "EnterCriticalSection", "LeaveCriticalSection" und ähnlichem. Damit kannst du verhindern, dass ein Thread Daten schreibt, während ein anderer Thread darauf zugreift.
-
Was mache ich flasch?
int var = 0; CRITICAL_SECTION CriticalSection; DWORD WINAPI Thread(LPVOID Data) { timeBeginPeriod(1); DWORD interval = 30; // in milliseconds ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); DWORD t0, t1 = ::timeGetTime(); while (true) { t0 = t1; printf("(%i)", var); t1 = ::timeGetTime(); DWORD diff = t1 - t0; if (diff < interval) Sleep(interval - diff); } return((DWORD)Data); } DWORD WINAPI Funktion(LPVOID Data) { while (true) __try { EnterCriticalSection(&CriticalSection); var = 1; //symbolisch für var löschen Sleep(1); var = 0; //symbolisch für var null terminieren } __finally { LeaveCriticalSection(&CriticalSection); } return((DWORD)Data); } #include <conio.h> int main() { HANDLE hThread = CreateThread(NULL, 0, Thread, (LPVOID)1, 0, 0); HANDLE hThread2 = CreateThread(NULL, 0, Funktion, (LPVOID)2, 0, 0); InitializeCriticalSection(&CriticalSection); while (getch() != 27); DeleteCriticalSection(&CriticalSection); CloseHandle(hThread); CloseHandle(hThread2); }Sleep soll andeuten, dass der Löschvorgang länger dauern kann. Die ganze Zeit soll kein anderer Thread drauf zugreifen können. Bei mir wird aber immer 1 ausgegeben ... es sollte doch 0 sein ... ich verstehe nicht, warum das nicht klappt.
MfG
-
Du musst das CriticalSection-Objekt schon initialisieren, bevor du es benutzt; nachdem du die Threads gestartet hast, ist es etwas zu spät.
Dann solltest du das CriticalSection-Objekt auch in beiden Threads benutzen, nicht nur in einem.
Und die Thread-Funktionen sollten irgendwann auch return aufrufen, sonst laufen die nach dem Ende von main() noch weiter und verursachen Speicherzugriffsfehler.
-
Auch wenn ich das in dieser Reienfolge mache:
InitializeCriticalSection(&CriticalSection); HANDLE hThread = CreateThread(NULL, 0, Thread, (LPVOID)1, 0, 0); HANDLE hThread2 = CreateThread(NULL, 0, Funktion, (LPVOID)2, 0, 0);besteht der beschriebene Fehler weiterhin ...
-
Hast du die anderen beiden Punkte, die ich genannt habe, auch umgesetzt?
-
Die andere Funktion hat keinen kritischen Bereich ... darum halte ich es nicht für sinnvoll, dort auch mit einem kritischen Bereich zu arbeiten ... habe statt der while(1) ne schleife genommen.
grüße
-
Thomas_ schrieb:
Die andere Funktion hat keinen kritischen Bereich ... darum halte ich es nicht für sinnvoll, dort auch mit einem kritischen Bereich zu arbeiten
Genau das ist aber der Sinn einer "CriticalSection": Zu einem Zeitpunkt kann sie nur ein einziger Thread in Beschlag nehmen. Du musst also EnterCriticalSection sowohl im ersten als auch im zweiten Thread aufrufen; dadurch verhinderst du, dass die sich in die Quere kommen. Denn wenn der erste Thread durch EnterCriticalSection den Zugriff erhalten hat, wird der andere Thread in EnterCriticalSection solange blockiert, bis der erste mit LeaveCriticalSection den Zugriff wieder freigibt.
-
zu beachten wäre da noch: eine critical section sollte möglichst schnell wieder verlassen werden. wenn ein thread mit 'Sleep' in einer CS wartet, müssen alle anderen auch so lange warten, die in der CS festhängen...

-
Ich möchte mich bei allen bedanken!
Du musst also EnterCriticalSection sowohl im ersten als auch im zweiten Thread aufrufen;
--> macht Sinn ... ich muss ja für einen einzigartigen Schreibzugriff, aber auch Lesezugriff achten ... das ist logisch ... und funzt sogar

--> auch das ist richtig ... Sleep sollte stellvertretend dür eine langandauernde Löschfunktion stehen. Es macht keinen Sinn Sleep dort hinzuschreiben ... aber für diesen Beispielzweck erfüllt es seine Funktion
Grüße & DANKE!!!
-
unter windows gibts doch sowas wie SetTimer() oder!?
-
gibt es ... wird dabei nicht das System lahm gelegt?? gut zu wiisen ... bin ich heute nicht um sonst aufgestanden

-
warum sollte das das system lahm legen!?