Thread aus einem anderen Thread stoppen!
-
sky21 schrieb:
Jochen Kalmbach schrieb:
Verwende entweder eine globale Variable, welche die Threads pollen (schlechte Lösung) oder ein globales (manual Reset) Event welches Du signalisierst und die Threads darauf warten können.
Ich verwende eigentlich immer die erste Variante. Also die..
Kannst du bitte hier erklären, weshalb die eine besser als die andere ist bzw. einge Gegenüberstellung der beiden Varianten machen.Der Vorteil ist eigentlich einfach: Du brauchst nicht pollen (pollen ist immer schlecht); somit sparst Du CPU Zeit.
-
Paul_C. schrieb:
Brauchst du nicht unbedingt. Du kannst auch bei WaitForSingleObject() die Zeit angeben, wielange er warten soll.
Dann hast Du ja aber nichts gewonnen, da Du ja dann schon wieder pollst (dann halt auf was anders)!
-
Versteh ich aber nicht. Wenn ich WaitForMultipleObjects in einem Thread aufrufe dann schläft der doch und kann nicht seine Aufgabe erledigen.
-
Ja 100% richtig verstanden... Aber die meisten Threads machen nicht ständig was sondern müssen uf was warten und dann machen sie was...
Aber das hängt natürlich vom speziellen Anwendungfall ab.
Wenn Du natürlich eine Rechenoperation durchführst die mehrere Minuten / Stunden geht, dann ist es sinnvoller eine globale Variable abzufragen.
-
Events sind zum Aufwecken von Threads geeignet aber nicht zum Stoppen.
-
Naja, implizit schon...
Du wartest auf den Event (WaitFor...) und wenn *dieser* Signalisiert wird, dann machst Du "return .."
-
Hallo,
danke für die vielen beiträge, aber irgendwie müssen die threads doch beendet werden können!
Ich habe einen haupt-thread, das programm selber, in diesem programm starte ich mehrere worker threads, können bis zu 50 oder 60 sein, aber es muß doch eine möglichkeit geben diese zu stoppen, ohne warten zu müssen dass die alle fertig sind!!!
Schliesslich hab ich ihre id's und handle gespeichert, über die soll das doch gehen können!
klick auf button stop->dann werden die id's und handles geholt(sind alle in einer CMap) einer nach dem anderen und an die ::TerminateThread(HANDLE hThread) übergeben, nur dass das nicht ganz so klapt!
und mit dem WaitForSingleObject(pThread->m_hThrad); , das ich in der thread-function aufrufe, hab ich memoryleaks?ka warumgrüsse
pixel
-
pixel schrieb:
danke für die vielen beiträge, aber irgendwie müssen die threads doch beendet werden können!
Ein Thread kann sich nur selber beenden. (Punkt)
pixel schrieb:
Ich habe einen haupt-thread, das programm selber, in diesem programm starte ich mehrere worker threads, können bis zu 50 oder 60 sein,
Du solltest vielleicht mal Dein Design überdenken... hört sich für mich ein wenig viel an...
pixel schrieb:
aber es muß doch eine möglichkeit geben diese zu stoppen, ohne warten zu müssen dass die alle fertig sind!!!
Ja. Signalisiere den Threads dass sie sich beenden sollen. Und dann sollten die das tun. Hab ich irgendwo geschrieben das Du warten musst bis sich der Thread beendet hat? (sollte man zwar tun aber notwendig ist dies nicht, wenn er nicht irgendwelche Ressourcen noch aufräumen muss; fazt: es wird empfohlen).
pixel schrieb:
Schliesslich hab ich ihre id's und handle gespeichert, über die soll das doch gehen können!
Das beenden geht darüber nicht... das warten auf den Thread schon
pixel schrieb:
klick auf button stop->dann werden die id's und handles geholt(sind alle in einer CMap) einer nach dem anderen und an die ::TerminateThread(HANDLE hThread) übergeben, nur dass das nicht ganz so klapt!
Und dass es Dir mehrmals erklärt wurde dass dies so nicht geht. Ganz abgesehen davon hast Du wohl auch nicht die Doku zu dieser Funktion gelesen; da steht das auch so...
pixel schrieb:
und mit dem WaitForSingleObject(pThread->m_hThrad); , das ich in der thread-function aufrufe, hab ich memoryleaks?ka warum
Löse zuerst mal das eine Problem, dann können wir über mögliche andere reden...
-
man könnte auch in der loop des threads SleepEx(0,TRUE) aufrufen und wenn er sich beenden soll mit QueueUserAPC() einen function pointer schicken. die funktion ruft der dann auf. in der funktion können dann irgendwelche aufräumaktionen gemacht werden und schliesslich ein ExitThread()
-
@jochen, danke!
dann lösen wir das erste problem zu erst, und gehen zu dem nächsten! Die singnale?
grüsse
pixel
-
net schrieb:
man könnte auch in der loop des threads SleepEx(0,TRUE) aufrufen und wenn er sich beenden soll mit QueueUserAPC() einen function pointer schicken. die funktion ruft der dann auf. in der funktion können dann irgendwelche aufräumaktionen gemacht werden und schliesslich ein ExitThread()
Wir wollten doch "pollen" verhindern...
Und einfach so ExitThread aufzurifen ist eine schlechte Idee, da die meisten Programmierer doch liebend gern die CRT verwenden... somit sollte man zumindest _endthread aufrufen...
Am einfachsten ist aber einfach ein "return" aus der ThreadProc
-
pixel schrieb:
dann lösen wir das erste problem zu erst, und gehen zu dem nächsten! Die singnale?
War das jetzt eine Frage oder eine Vermutung?
-
Jochen Kalmbach schrieb:
Am einfachsten ist aber einfach ein "return" aus der ThreadProc
nur musste den thread dazu kriegen, dass er da auch hinspringt.
naja, aber wozu gibt es so schicke funktionen wie SetThreadContext()?
einfach mal eben den instruction pointer von aussen auf das 'return' setzenedit: ach, noch was. wem threads zu suspekt sind, der könnte auch 'fibers' nehmen. die laufen in einem thread d.h. man bekommt nicht solche probleme, wenn's ums beenden geht.
-
net schrieb:
naja, aber wozu gibt es so schicke funktionen wie SetThreadContext()?
Ich hoffe das war jetzt nicht ernst gemeint
Weil dann kannst Du auch gleich TerminateThread verwenden
-
Jochen Kalmbach schrieb:
net schrieb:
naja, aber wozu gibt es so schicke funktionen wie SetThreadContext()?
Ich hoffe das war jetzt nicht ernst gemeint
Weil dann kannst Du auch gleich TerminateThread verwenden
na, teils/teils. wenn man solche verschärften massnahmen anwendet muss man schon ganz genau wissen was man tut mit so einem 'manuellen context switch'. aber eine möglichkeit ist es auf jeden fall.
-
Bitte bring mal Beispielcode Jochen.
-
net schrieb:
eine möglichkeit ist es auf jeden fall.
Da kann ich Dir nur wiedersprechen... wer sowas macht (also den Thread "abschiesst" egal ob jetzt mittels TerminateThread oder SetThreadContext) kann gleich ExitProcess aufrufen...
-
:-)) schrieb:
Bitte bring mal Beispielcode Jochen.
Ist das denn soo schwierig?
Also hier die Event gesteuerte Version:
#include <stdio.h> #include <windows.h> #include <tchar.h> DWORD WINAPI MyThread(LPVOID pData) { HANDLE hWaitHandles[2]; hWaitHandles[0] = (HANDLE) pData; hWaitHandles[1] = CreateEvent(NULL, FALSE, FALSE, NULL); DWORD dwRes; do { dwRes = WaitForMultipleObjects(2, hWaitHandles, FALSE, INFINITE); if (dwRes == WAIT_OBJECT_0+1) { // es gibt was anderes zu tun... } } while (dwRes != WAIT_OBJECT_0); CloseHandle(hWaitHandles[1]); return 0; } int _tmain() { HANDLE hEndEvent = CreateEvent(NULL, TRUE, FALSE, NULL); DWORD dwThreadId; HANDLE hThread = CreateThread(NULL, 0, MyThread, hEndEvent, 0, &dwThreadId); // mache noch was anderes... SetEvent(hEndEvent); WaitForSingleObject(hThread, INFINITE); }
Und hier mit der globalen Variable:
#include <stdio.h> #include <windows.h> #include <tchar.h> bool volatile g_bEndThread = false; DWORD WINAPI MyThread(LPVOID pData) { while(g_bEndThread == false) { // do some long running calculation } return 0; } int _tmain() { DWORD dwThreadId; HANDLE hThread = CreateThread(NULL, 0, MyThread, NULL, 0, &dwThreadId); // mache noch was anderes... g_bEndThread = true; WaitForSingleObject(hThread, INFINITE); }
-
Melde mich auch wieder zurück.
Das, was ich am Anfang über WaitForSingleObject() gesagt habe, da hat Jochen natürlich Recht. Dann wäre man beim Polling. Sorry.
Aber jemand schrieb hier (unregistriert: "event-spezialist"), dass man Events nicht zum Beenden nutzen sollte?
Wieso nicht? Finde ich persönlich eine wunderbare Lösung.
Wie sollte es sonst gehen? Außer mit der globalen Variable? :xmas1:
-
In MyThread auch noch ein Event erstellen? Wofür das?