Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » VC++ / MFC » Thread-Pending nach Beendigung

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
06.07.2010, 09:52 Uhr
cmos



Hallo,
wenn ich meinen Workerthread beende, dann ist der noch
im Pending-Modus. Nur ganz selten ist er wirklich beendet.

Folgend das Stück Code was den Thread erstellt.

C++:
startEvent     = ::CreateEvent(NULL, FALSE, FALSE, "startEvent");
stopEvent     = ::CreateEvent(NULL, FALSE, FALSE, "stopEvent");
stoppedEvent = ::CreateEvent(NULL, FALSE, FALSE, "stoppedEvent");
thread = ::AfxBeginThread(Application::applicationThread, this, priority);    



In der Threadproc ist eine while(TRUE) Schleife. Um ein Beenden von außen
abzufangen benutze ich

C++:
while(TRUE)
{
  if(::WaitForSingleObject(stopEvent, 5) ==  WAIT_OBJECT_0)
  {
    break;
  }
  // zeug
}
::SetEvent(stoppedEvent);
return 0;



Das funktioniert auch soweit, die Threadfunktion wird verlassen. Im Hauptprogramm
warte ich mit

C++:
::AtlWaitWithMessageLoop(stoppedEvent);


darauf, das der Threadbeendet wird, besser gesagt, die Funktion verlassen wird, da ja am
Ende das stoppedEvent gesetzt wird. Das funktioniert auch.

Nur passiert es sehr oft (zu 99%) dass, das ganze Programm nicht komplett beendet ist.
Ich habe mir darauf hin mit GetExitCodeThread den Exitcode geben lassen. Und dieser ist
STATUS_PENDING. Anstatt return 0 am Ende der ThreadProc habe ich auch einmal AfxEndThread(..) probiert. Aber auch da ist das gleiche Verhalten zu beobachten.
Das Problem ist, dass das Programm nicht komplett beendet wird. Das merkt man daran,
dass nach dem "Programmende" das Visual Studio immer noch darauf wartet das es beendet wird und das man nichts neu kompilieren oder Debuggen kann. Wenn ja, wird man gefragt, ob man den Debug-Modus verlassen möchte.

Habe ich noch etwas wichtiges vergessen ?

Grüße,
cmos
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
06.07.2010, 10:12 Uhr
cmos



Also, ich habe gerade AtlWaitWithMessageLoop durch WaitForSingleObject ausgetauscht.
Jetzt wird alles richtig beendet und nichts hängt mehr. Aber wenn man mit WaitForSingleOBject im Hauptthread wartet, wird ja alles weitergehende blockiert.
Dafür gibts ja eigentlich AtlWaitWithMessageLoop. Wenn ich an der Stelle von AtlWaitWithMEssageLoop einen Breakpoint setze und von dort mit F5 wieder fortfahre, wird alles ordnungsgemäß beendet.

Hat jemand eine Idee ?

Dieser Post wurde am 06.07.2010 um 10:17 Uhr von cmos editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
06.07.2010, 10:15 Uhr
ao

(Operator)


Logikfehler: Der Workerthread setzt das Stopped-Event, d.h. wenn das Hauptprogramm dieses Event bekommt, läuft der Workerthread ja noch. Vom Zufall hängts dann ab, ob er schnell genug geschlossen wird, bevor das Hauptprogramm wieder an die Reihe kommt. Sowas nennt man Race Condition.

Testweise (nur testweise!) könntest du mal versuchen, nach dem AtlWaitWithMessageLoop ein Sleep (1000) oder so zu machen, um den Worker Zeit zu geben, sich wirklich zu beenden. Damit wird die Race Condition nicht gelöst, sondern nur gemildert, darum ist das keine richtige Problemlösung, sondern nur ein Versuch und eine Hilfe für dich zum Verständnis.

Ansonsten heißt der Weg, aufs Ende eines Threads zu warten, normalerweise "Join". Das Hauptprogramm macht Join(workerThread); und blockiert sich damit so lange, wie der Worker noch im System ist. Guck mal nach, ob du bei den AFX-Threads etwas Passendes findest.


Zitat:
Also, ich habe gerade AtlWaitWithMessageLoop durch WaitForSingleObject ausgetauscht. Jetzt wird alles richtig beendet und nichts hängt mehr.

Ich glaube, dass das nur zufällig klappt. Richtig programmiert ist es immer noch nicht, d.h. der Fehler kann wiederkommen.

Dieser Post wurde am 06.07.2010 um 10:18 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
06.07.2010, 10:24 Uhr
cmos



Hallo,
danke für den Hinweis. Das Sleep hat bei mir aber nichts geändert.
Ich habe auf der Suche nach der Problemlösung diesen Link hier
gefunden
www.codeguru.com/forum/showthread.php?t=43205
mit dem Titel "Proven Deadlock Bug in AtlWaitWithMessageLoop"

Ob man das nun für bare Münze nehmen kann, weiß ich nicht. Dafür stehe ich nicht
Tiefgenug in der Materie.

Grüße,
cmos
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
06.07.2010, 10:39 Uhr
cmos



Hallo nochmal,
ich denke ich habe den Fehler gefunden. AtlWaitWithMessageLoop sollte ja bestimmt nur
in Threads eingesetzt werden die auch ne MessagePump haben, also GUI Threads.
Ich habe es innerhalb einer Klasse aufgerufen die das nicht hat. Könnte das der Fehler
gewesen sein ? Früher hatte ich auch schon AtlWaitWithMessageLoop verwendet, aber
innerhalb der GUI um während des Threadlaufs noch mit der GUI arbeiten zu können
während ich auf das Threadende gewartet habe.

Grüße,
cmos
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ VC++ / MFC ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: