Thread über Event beenden klappt unter Vista nicht
-
Ich habe folgenden Thread, welcher mit _beginthreadex gestartet wird.
unsigned CAudioIn::readSocketThread(LPVOID pParam) { CAudioIn* pThis = (CAudioIn*)pParam; ResetEvent(pThis->m_eventThreadHasTerminated); SOCKADDR_IN saRemote; int addr_len = sizeof(SOCKADDR_IN); bool bStop = false; while(!bStop) { char buf[1500]; //AfxMessageBox(L"readSocketThread"); int nLen = recvfrom(pThis->m_sSocket, buf, 1500, 0, (SOCKADDR*)&saRemote, &addr_len); if (WaitForSingleObject(pThis->m_eventTerminateThread, 0)==WAIT_OBJECT_0) { AfxMessageBox(L"Abbruch readSocketThread"); bStop=true; break; } if(nLen > 0) { //Do Something with the RTP Packet } else continue; } SetEvent(pThis->m_eventThreadHasTerminated); AfxMessageBox(L"Terminated Event gesetzt"); _endthreadex(0); return 0; }Hieru gibt es eine do_stop() Methode
USES_CONVERSION; DWORD dwWfsoRes = 0; while (WaitForSingleObject(m_eventThreadHasTerminated, 0) != WAIT_OBJECT_0) { SOCKADDR_IN saRemote; saRemote.sin_family = AF_INET; //AfxMessageBox(A2T(pStream->getDestIp().c_str())); saRemote.sin_addr.s_addr = inet_addr(pStream->getDestIp().c_str()); saRemote.sin_port = htons(pStream->getDestPort()); int nLen = sendto(m_sSocket, "0", 1, 0, (SOCKADDR*)&saRemote, sizeof(saRemote)); if(!SetEvent(m_eventTerminateThread)) AfxMessageBox(L"Event wurde nicht gesetzt"); AfxMessageBox(L"Waitingfor"); Sleep(50); //dwWfsoRes = WaitForSingleObject(m_eventThreadHasTerminated, INFINITE); } m_bIsStarted = false; return true;Diese setzt also den Event eventTerminateThread welcher im Thread für das Abbrechen der Schleife sorgen soll.
Unter XP läuft dieses Vorgehen auch einwandfrei.Seltsam ist auch, dass die Applikation den Event erkennt wenn ich im Thread die einkommentierte MessageBox(AfxMessageBox(L"readSocketThread")) auskommentiere und dann mit OK bestätige. Ist diese aber nicht auskommentiert schweint es so als würde der Thread das Event nie erhalten.
Jemand eine Idee woran das liegen könnte?
Gruß
Crazy
-
1. Warum benutzt Du überhaupt ein Event um dem Thread einen terminate mitzuteilen, wenn Du sowieso nicht wartest. Ein Flag tut es hier auch.
2. Benötigst Du kein Event m_eventThreadHasTerminated. Du kannst das Handle des Threads direkt nutzen um das zu prüfen.
3. Der Aufruf von _endthreadex ist unnötig. Ein return genügt und ist portabler.
4. Du benutzt die MFC aber nicht AfxBeginThread, so wie ich das sehe! Den entsprechenden Warnhinweis aufmein Blog hast Du schon.
http://blog.m-ri.de/index.php/2008/02/28/afxbeginthread-versus-_beginthreadex/
5. Bist Du sicher, dass recvfrom überhaupt zurückkehrt. Wenn nicht kann der Thread nicht terminieren.
6. Trace-Ausgaben im Debugger sind flexibler als Message Boxen.
7. USES_CONVERSION und ein Schleife ist tödlich. Verwende lieber CA2T, als A2T!
-
1.) Mit nem Flag funktioniert es jetzt.
3.) ist rausgenommen hatte es nur in einem Beispiel so gesehen.
4.) Mein Gott Threads:D. Ich muss mich da wohl noch viel intensiver mit auseinandersetzen:D. Deinen Blog habe ich aber gelesen. Danke.
5.) Dafür hatte ich ja denn Dummy rausgeschickt, das vom Server noch eine Antwort kommt.
6.) Das war das Problem. Im Debug Mode hatte es ja auch geklappt deshalb die Message Boxen um im Release zu sehen was passiert.
7.) Warum ist das tödlich?
-
@7. A2T verwendet alloca, dass führt dazu dass Speicher auf dem Stack allokiert wird. Jeder Dchleifendurchlauf allokiert dann neuen Speicher vom Stack... Den Rest kannst Du Dir denken.
CA2T verwendet den Heap.
-
Alles klar gut zu wissen.
Danke für den Hinweis.