Preisfrage: Worker Threads beenden
-
Hallo,
ich bin schon ganz verzweifelt... vielleicht kann mir hier jemand helfen.
Folgendes: Ich habe eine DLL geschrieben von der aus 4 Worker-Threads erzeugt werden. Diese 4 Threads laufen ständig und kümmern sich um das Bearbeiten von Sende und Receive-Queues. Die Synchronisation geschieht über Events.
Alle 4 Threads sehen somit ungefähr so aus:while(!m_ende)
m_event.Lock();
if (m_ende) break;// Aufgabe Erledigen
...
}
return 0;Jeder Thread reagiert auf ein anderes Event.
Wenn ich nun diese DLL wieder schließen will, sprich die Instanz der DLL-Klasse, welche die 4 Worker-Threads beinhaltet beende, muss ich mich irgendwie um die Beendung der 4-Worker-Threads kümmern, da ich ansonsten eine Kernel-Exception im Hauptprogramm, welches die DLL benutzt, bekomme.Ganz einfach (dachte ich): Ich habe ja extra eine Member-Variable in der DLL-Klasse (m_ende), die ich nur auf TRUE setzen muss. Anschließend löse ich für jeden Worker-Thread das entsprechende Event aus, damit er im nächsten Schritt auf die "if (m_ende) break;"-Zeile stößt. Falls ein Thread gerade in der Bearbeitung ist, würde er bei der oberen While-Schleife die Thread-Funktion verlassen.... Es ist also für alles gesorgt....
Im Destruktor gibt es für alle 4 Threads den folgenden Code, der garantiert, dass es erst weiter geht, wenn der jeweilige Thread beendet worden ist:m_event->SetEvent();
do {
DWORD exitCode;
GetExitCodeThread(m_pThread1->m_hThread, &exitCode);
if (exitCode == 0) break;
_sleep(0);
} while(TRUE);Komischerweise bekommt ich aber immer eine Kernel-Exception, wenn ich im Destruktor der DLL-Klasse die Events auslöse. D.h. ich kann die Events auslösen, die Thread-Funktionen werden auch verlassen, aber im MFC-Code knallt es bei dem Aufruf von AfxEndThread(0) (habe mal in den MFC-Code debugged).
Das passiert aber nur, wenn ich die Events im Destruktor auslöse. Wenn ich die Threads mal verunstalte und sie pollen lasse, geht alles einwandfrei...
Wieso zum Teufel passiert nach SetEvent() im Destruktor der DLL-Klasse nur noch Käse, wenn ein Thread sich beendet?
Und wie kann ich die Threads sauber (!) beenden ohne zu pollen?
Danke
-
In der MSDN steht, dass du CWinThread auf zwei Arten beenden kannst.
- AfxEndThread(0) von innerhalb des Threads.
- Du verlässt einfach die Funktion, in der der Thread gestartet wurde.
Hast du vielleicht versucht, die Threads doppelt zu beenden?
-
CLoop schrieb:
In der MSDN steht, dass du CWinThread auf zwei Arten beenden kannst.
- AfxEndThread(0) von innerhalb des Threads.
- Du verlässt einfach die Funktion, in der der Thread gestartet wurde.
Hast du vielleicht versucht, die Threads doppelt zu beenden?
Hallo...
Ich möchte ja, dass der Thread sich selber beendet, in dem ich die Thread funktion einfach verlasse.
Damit der Threadfunktion aber beendet wird, muss ich ihm dises ja sagen. Das mache ich über ein CEvent.
Das geht auch alles wunderbar. Nachdem die Thread-Funktion aber abgearbeitet worden ist, kann man im Debugger sehen, dass noch MFC-Code ausgeführt wird. Und an der Stelle AfxEndThread, welche automatisch beim Verlassen einer Worker-Thread-Funktion aufgerufen wird, gibt es eine Kernel-Exception.....
-
Also, die Threadfunktion returned und das beendet den Thread schon. Trotzdem rufst du AfxEndThread noch mal auf, scheint mir krititsch. Was sagt denn der Debugger, gibt es irgendein ASSERT, was du verletzt hast? Und, warum wird noch Code ausgeführt, wenn die Threadfunktion doch schon beendet ist?
-
Hey, um das noch mal klarzukriegen. Du übergibst ja auch noch ne Funktion an den Thread. Wenn die returned, ist auch Schluss. Das wären dann drei Möglichkeiten, den Thread zu beenden.
P.S.: Ich finde den Code, den du gepostet hast, nicht so aufschlussreich.
-
CLoop schrieb:
Also, die Threadfunktion returned und das beendet den Thread schon. Trotzdem rufst du AfxEndThread noch mal auf, scheint mir krititsch. Was sagt denn der Debugger, gibt es irgendein ASSERT, was du verletzt hast? Und, warum wird noch Code ausgeführt, wenn die Threadfunktion doch schon beendet ist?
Nene... ich rufe nicht AfxEndThread auf... das geschieht automatisch im MFC-Code, der beim Verlassen der Thread-Funktion gestartet wird...
Aber ich habe nun eine andere Sache herausgefunden:
Irgendwie liegt es daran, dass ich alles im Destruktor mache. Obwohl es als aller erstes passiert, gibt es Probleme, die nicht auftreten, wenn ich den Code von einer beliebigen anderen Stelle aus starte...Komisch...
-
MIr scheint auch deine Funktion im Thread Kritisch. Gib denen mal etwas Zeit.
Baue hinundwieder mal Sleep(0) ein.