Thread beenden: Es klappt einfach nicht.
-
Mit Hilfe der MSDN, der Forenbeiträge und der FAQ habe ich mir die Theman zu 'WaitForSingleObject' durchgelesen (und nicht immer verstanden). Versuchte das Ganze auf mein Programm umzusetzen. Bisher erfolglos.
...Bei mir funktioniert es nicht und ich hoffe dass mir jemand dabei helfen kann.
Mein Ziel: Ich will, dass ein Thread ordnungsgemäss beendet werden kann.Meine Bespielapplikation kennt die folgenden relevanten Methoden:
Die Thread Methode:
UINT ThreadReceive(LPVOID data){ MyClassDlg* dlg = (MyClassDlg*) data; // kompletter Dialog dlg->m_List1.AddString("starting thread to receive data..."); while(dlg->m_bEndThread == false){ dlg->m_List1.AddString("1"); //m_List1 ist ein CListCtrl Sleep(1000); dlg->m_List1.AddString("2"); Sleep(1000); dlg->m_List1.AddString("3"); Sleep(1000); dlg->m_List1.AddString("4"); Sleep(1000); dlg->m_List1.AddString("5"); Sleep(1000); dlg->m_List1.AddString("6"); } return 0; }
Die OnButtonStart Methode:
void MyClassDlg::OnButton_Start(){ m_bEndThread = false; // typ 'bool' // m_pThread ist vom typ 'CWinThread*' m_pThread = AfxBeginThread(ThreadReceive, (LPVOID)this, THREAD_PRIORITY_NORMAL); }
so und nun wenn ich die Stopp-Taste klicke:
void MyClassDlg::OnButton_Close(){ m_bEndThread = true; m_List1.AddString("stopping"); HANDLE hndThread = m_pThread->m_hThread; WaitForSingleObject(hndThread, INFINITE); m_List1.AddString("thread stop"); }
Der Output ist nun der folgende
1
2
< jetzt klicke ich auf stopp>so, das Programm bleit bei der 'WaitForSingleObject' Methode hängen.
Wenn man nun INFINITE durch z.b. 5000 ersetze, dann passiert folgendes:1
2
< jetzt klicke ich auf stopp>
<jetzt passiert 5sek. nix>
stopping
thread stop
3
4
5
6Also weshalb funktioniert das 'INFINITE' bei mir nicht? obwohl ich den bool-Wert verändert habe? Meiner Meinung sollte die Ausgabe die folgende sein:
1
2
< jetzt klicke ich auf stopp>
stopping
3
4
5
6
thread stopJetzt noch eine Anmerkdung:
Beim 'WaitForSingleObject' Parameter #1 (handle) steht in der MSDN der folgende Text:hHandle
Handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section.
Windows NT: The handle must have SYNCHRONIZE access. For more information, see Standard Access Rights.Verstehe diesen Text nicht. Also ich habe hier ein Win2000 System. Kann das ein Grund für das nichtfunktionieren des obigen Codes sein?
-
Du übergibst deinem Thread die Klasse MyClassDlg. Dann fragst du die Variable MyClassDlg.m_bEndThread ab. Soweit so gut.
ABER:
dann setzt du in deiner Klasse CMyRS232_TesterDlg die Variable m_bEndThread. Woher soll nun der Thread von der anderen Vaiable wissen?
Die Variable MyClassDlg.m_bEndThread ist unverändert
-
Nachdem Du den Thread gestoppt hast sagst Du Deine Anwendung soll für eine unendliche Zeitspanne auf den Thread warten. Der Thread ist aber wohl gestoppt und ändert seinen Zustand nicht, daher bleibt Deine Anwendung auch bei WaitForSingleObject stehen.
Wenn Du die 5000 Einträgst, dann geht die Anwendungen automatisch spätestens nach dieser Zeit (oder früher, wenn der Thread den Zustand ändert) weiter.Wenn Du den Rückgabewert von WaitForSingleObject bei einer nicht-unendlichen Zeitspanne überprüfst, dann bekommst Du sicher WAIT_TIME zurück (siehe MSDN)...
-
Airdamn schrieb:
Nachdem Du den Thread gestoppt hast sagst Du Deine Anwendung soll für eine unendliche Zeitspanne auf den Thread warten. Der Thread ist aber wohl gestoppt und ändert seinen Zustand nicht, daher bleibt Deine Anwendung auch bei WaitForSingleObject stehen.
Wenn Du die 5000 Einträgst, dann geht die Anwendungen automatisch spätestens nach dieser Zeit (oder früher, wenn der Thread den Zustand ändert) weiter.Wenn Du den Rückgabewert von WaitForSingleObject bei einer nicht-unendlichen Zeitspanne überprüfst, dann bekommst Du sicher WAIT_TIME zurück (siehe MSDN)...
Das beenden des Threads sollte schon so klappen. Er muss nur die richtige Variable setzen
-
Horst2 schrieb:
Du übergibst deinem Thread die Klasse MyClassDlg. Dann fragst du die Variable MyClassDlg.m_bEndThread ab. Soweit so gut.
ABER:
dann setzt du in deiner Klasse CMyRS232_TesterDlg die Variable m_bEndThread. Woher soll nun der Thread von der anderen Vaiable wissen?
Die Variable MyClassDlg.m_bEndThread ist unverändert
Ahh crap. Habe die Klasse vergessen umzubenennen! alle Methoden gehören leider in die Klasse MyClassDlg!
-
Airdamn schrieb:
Nachdem Du den Thread gestoppt hast sagst Du Deine Anwendung soll für eine unendliche Zeitspanne auf den Thread warten. Der Thread ist aber wohl gestoppt und ändert seinen Zustand nicht, daher bleibt Deine Anwendung auch bei WaitForSingleObject stehen.
Wenn Du die 5000 Einträgst, dann geht die Anwendungen automatisch spätestens nach dieser Zeit (oder früher, wenn der Thread den Zustand ändert) weiter.Wenn Du den Rückgabewert von WaitForSingleObject bei einer nicht-unendlichen Zeitspanne überprüfst, dann bekommst Du sicher WAIT_TIME zurück (siehe MSDN)...
Ja ich erhalte WAIT_TIMEOUT, wenn ich 5000ms warte. Dennoch, eigentlich müsste die Threadmethode ja noch fortgefahren werden (also bis '6' ausgeben'), erst DANN merkt die while-Schlaufe, dass in der Zwischenzeit das Abbruchkritierium erfüllt worden ist und springt daher aus der while Schlaufe. Es müsste also folgendes Ausgegeben werden:
1
2
< jetzt klicke ich auf stopp>
stopping
3
4
5
6
thread stopAber genau das tut er nicht - Es ist fast so, also ob der Thread solange wartet, und nicht die Methode in der Dialogklasse. I just don't get it. Help!
-
Das hat eine ganz einfache Ursache: die Message Loop. Das Hinzufügen zur Listbox passiert über Messages, die in der Message Loop des Hauptthreads abgearbeitet werden. Da dieser aber steht (in WaitForSingleObject), tut sich nix. Erst wenn er wieder lebt, werden die aufgestauten Nachrichten bearbeitet. Wenn du die Zeilen in ein File schreiben würdest, könntest du die Reihenfolge beobachten, die du erwartest.
-
Ringding schrieb:
Das hat eine ganz einfache Ursache: die Message Loop. Das Hinzufügen zur Listbox passiert über Messages, die in der Message Loop des Hauptthreads abgearbeitet werden. Da dieser aber steht (in WaitForSingleObject), tut sich nix. Erst wenn er wieder lebt, werden die aufgestauten Nachrichten bearbeitet. Wenn du die Zeilen in ein File schreiben würdest, könntest du die Reihenfolge beobachten, die du erwartest.
Ja das habe ich verstanden! Danke.
Inwiefern dies allerdings mein Problem löst, kann ich nocht nich burteilen - vermutlich muss ich halt ein 'work around' machen.