Thread kontrolliert beenden



  • Nabend,

    habe schon ein wenig im Netz rumgesuft - wollte das Thema jedoch nochmal aufschnappen.

    Ich habe zwei Threads in einem Prozess Lauf, einem den Main-Thread + SubThread. Den SubThread möchte ich kontrolliert beenden, indem ich diesem "sage" Shutdown vorgang eingeleitet, bitte jetzt "alle Prozesse" ebenfalls beenden.
    ---> Solange bitte warten!

    Naja, grundlegend ist mir die Idee gekommen, mach ich zwei bool Variablen, eine für den Zustand und eine für den Einleitungsvorgang, die vom zweiten Thread sequenziell abgefragt wird.
    Die Andere Variable soll den Zustand beschreiben AN/AUS. Somit setzte ich die DoQuit Variable auf true, und warte bis der Zustand "IsRunning" auf false ist.

    Evt. gibt jemand ein Satement dazu ab?

    Mfg



  • Mein Statement: An sich finde ich die Idee mit den 2 Bool-Variablen ganz gut! Das ist simpel, und, solange du nur mit je einem Thread je eine Variable beschreibst, sollte das auch Thread-sicher sein.

    Ich persönlich benutze eine andere Methode: Ich nehme eine auch eine bool Variable (bPleaseExit oder so...). Wenn der Hauptthread gerne hätte, dass sich der Sub-Thread beendet, setzt er diese auf true.
    Der Sub-Thread checkt regelmäßig die bPleaseExit, wenn die auf true ist, beendet er friedlich sein Dasein.

    Der Haupt-Thread lässt dem Sub-Thread 500 ms Zeit, sich zu beenden, ansonsten schließt er ihn. Du kannst mit WaitForSingleObject dann prüfen, ob der Thread schon beendet ist.
    So z.B.

    bPleaseExit = true;
    if ( WAIT_TIMEOUT == WaitForSingleObject( hThreadHandle, 500 ) )
    {
        TerminateThread( hThreadHandle, 0 );
    }
    // Thread ist weg  :D
    

    Grüße,
    Badestrand



  • Ich habe nicht ganz exakt verstanden wie Du das meinst. Der Main Thread soll auf das Ende des SubThredas Warten und dann soll sich der Prozess selbst beenden? Vielleicht mal die wichtigen Codezeilen posten.

    Generell bevorzuge ich Events zum Warten auf das Ende eines Threads:
    ::WaitForSingleObject(hEvent,INFINITE);
    Diese Anweisung wartet solange bis das Event (zu erzeugen mit ::CreateEvent(...)) im Zustand "signaled" ist.



  • NickHappy schrieb:

    Ich habe nicht ganz exakt verstanden wie Du das meinst. Der Main Thread soll auf das Ende des SubThredas Warten und dann soll sich der Prozess selbst beenden? Vielleicht mal die wichtigen Codezeilen posten.

    Ich denke, er will seinen Prozess beenden. Und bevor das getan ist, will er alle Threads sauber beenden.

    NickHappy schrieb:

    Generell bevorzuge ich Events zum Warten auf das Ende eines Threads:
    ::WaitForSingleObject(hEvent,INFINITE);

    Naja, ich halte immer wenig von dem INIFINTE-Warten. Kann dazu führen, dass der wartende Thread hängen bleibt ! 👎 ⚠



  • Badestrand schrieb:

    NickHappy schrieb:

    Generell bevorzuge ich Events zum Warten auf das Ende eines Threads:
    ::WaitForSingleObject(hEvent,INFINITE);

    Naja, ich halte immer wenig von dem INIFINTE-Warten. Kann dazu führen, dass der wartende Thread hängen bleibt ! 👎 ⚠

    Warum soll den der Thread "hängenbleiben"?
    Wenn sowas vorkommt, dann würde ich mal nach dem Fehler suchen und nicht einen Fehler mit einem anderen beheben (TerminateThread aufzurufen ist IMHO eine Todsünde:
    http://blog.kalmbachnet.de/?postid=6
    http://blog.kalmbachnet.de/?postid=16
    http://blog.kalmbachnet.de/?postid=17
    )



  • Zu: Warum soll der Thread hängenbleiben?
    Wenn sich (aus irgendeinem Grund) der Thread nicht selber beenden sollte, wartet der Hauptthread logischerweise endlos-lange. Das bezeichne ich als hängenbleiben...

    Bei mir gab es mit TerminateThread noch nie einen dead-lock. Schien mir ziemlich speziell zu sein, mit dem printf. Wenn beide Threads printf benutzen und wenn der eine Thread suspended wird und und und...

    Da nehm ich dieses (für mich geringeres) Risiko des Deadlocks auf mich. Wie soll man einen Thread auch sonst zwangs-beenden??



  • Badestrand schrieb:

    Da nehm ich dieses (für mich geringeres) Risiko des Deadlocks auf mich. Wie soll man einen Thread auch sonst zwangs-beenden??

    man könnte ihn z.b. abschiessen. wenn der in irgend'ner systemfunktion festsitzt und niemals an deinem bool 'please_exit' vorbeikommt, kannste mit 'SetThreadContext' seinen pc von ausserhalb auf 0 setzen, das sollte ihn augenblicklich killen (musst ihn natürlich in einen exception handler einpacken und im __except-pfad steht dann ein return).

    bleibt nur noch die frage, ob das nicht genauso fies ist wie ein 'TerminateThread' 😉

    kleine berichtigung: der thread darf natürlich nicht im wait-state festhängen damit das funzt...



  • Badestrand schrieb:

    Wenn sich (aus irgendeinem Grund) der Thread nicht selber beenden sollte

    , musst du den Grund suchen...TerminateThread ist, wie Jochen schon sagte: 👎



  • Badestrand schrieb:

    Wenn sich (aus irgendeinem Grund) der Thread nicht selber beenden sollte

    Das ist für mich genau der Punkt: Such doch bitte nach dem Fehler, warum sich der Thread nicht beendet und murks nicht an anderere Stelle um den Fehler rum.



  • Hallo,

    erstmal Danke für das Interesse an diesem Thread, es werden hier viele gute Dinge aufgegriffen.
    Ich hab mir die letzten Stunden evt. eine etwas bessere Variante einfallen lassen. Es gibt nicht mehr nur boolische Variablen sondern eine einzige Int-Variable und eine einzige bool Variable.
    Die bool Variable initiiert den Shutdown-Vorgang, der entsprechend in (ALLEN) Threads bearbeitet wird.
    Sollte ein Thread beginnen wird die Int-Variable erhöht, sollte ein Thread beendet werden (legitim) wird diese um 1 erniedrigt.

    => DLL-Loader Prinzip

    Parallel wird gewartet, bis die Int-Variable (anz. der offenen Threads) bei null angelangt ist. Sollte dies nicht innerhalb 10(bzw. auch 0.5) Sekunden geschehen, werden alle Threads per TerminateThread manuell beendet (als Sicherung während der Programmierung, für die Fehlersuche!! 😉 )

    Bye



  • JayJay schrieb:

    Sollte ein Thread beginnen wird die Int-Variable erhöht, sollte ein Thread beendet werden (legitim) wird diese um 1 erniedrigt.

    Dies darfst Du dann aber nur mit den "Interlocked"-Funktionen machen!

    Aber dann kannst Du eigentlich gleiche Semaphore verwenden, da kannst Du auch drauf warten.

    Aber das ist wie oben erwähnt bei Threads gar nicht nötig, da Du auf das Handle des Threads einfach warten kannst (oder auch auf mehrere).

    JayJay schrieb:

    werden alle Threads per TerminateThread manuell beendet (als Sicherung während der Programmierung, für die Fehlersuche!! 😉 )

    Wie gesagt: ich kann es nicht verstehen, dass man Threads abschiessen muss... ok, nur wenn man zu faul ist den Fehler zu suchen...



  • JayJay schrieb:
    werden alle Threads per TerminateThread manuell beendet (als Sicherung während der Programmierung, für die Fehlersuche!! 😉 )

    Wie gesagt: ich kann es nicht verstehen, dass man Threads abschiessen muss... ok, nur wenn man zu faul ist den Fehler zu suchen...

    Naja wie gesagt, zu letzt werden diese Dinge komplett entfernt!! 😉



  • Achja, wie soll ich eig. das verstehen?

    Dies darfst Du dann aber nur mit den "Interlocked"-Funktionen machen!



  • InterlockedIncrement
    InterlockedDecrement



  • JayJay schrieb:

    Achja, wie soll ich eig. das verstehen?

    Dies darfst Du dann aber nur mit den "Interlocked"-Funktionen machen!

    In etwa so 😉 : http://www.winapi.net/index.php?inhalt=t1


Anmelden zum Antworten