Thread beenden
-
Hallo zusammen,
Ich habe die Aufgabe eine Ansteuerung für ein 3-Achs-Portal zu schreiben.
Dabei muss ich gleichzeitig fahren, messen und die NotAus-Überwachung realisieren. Aus diesem Grund gibt es verschiedene Threads. Da unterschiedliche Bewegungsthreads zum Einsatz kommen können (aber nicht gleichzeitig) muss im NotAus-Fall alle sicherheitshalber beenden. Die einzelnen Threads lege ich mit new Thread an und beende sie mit Thread->Terminate(). Wenn ich aber einen Thread beenden möchte der entweder bereits abgelaufen oder noch nicht gestartet wurde, gibt es böse eine Fehlermeldung. Wie kann man die Existens solcher Threads überprüfen?
-
Andreas1333 schrieb:
Wenn ich aber einen Thread beenden möchte der entweder bereits abgelaufen oder noch nicht gestartet wurde, gibt es böse eine Fehlermeldung.
Na welche denn?
Würde es mal mit "if(Thread != NULL)Thread->Terminate()" oder mit "try{Thread->Terminate();}catch(...){} versuchen...
-
Welche Meldung genau kommt weiß ich jetzt nicht, da alles auf Arbeit liegt. Mit try
catch(...) bekomme ich das Ganze abgefangen, hatte aber gehofft das eine Möglichkeit ohne Exception gibt.Angelegt wird der Thread z.B. mit:
TThread* NewMove;NewMove = new Thread_move(false);
NewMove->OnTerminate = DeleteMove;Und diese Variable NewMove kennt er in bestimmten Fällen (Bewegung zu Ende oder noch nicht gestartet) nicht. Laufende Threads stellen dagegen kein Problem dar.
-
Wenn du eh ein OnTerminate hast, könntest du doch einfach für jedes Array eine bool-Variable anlegen, in der steht, ob der Thread existiert. Bei new setzt du sie auf true, im OnTerminate auf false...
Brauchts aber nur, wenn "if(NewMove)" nicht ausreicht.
-
Das mit dem Array würde gehen kann aber in ungünstigen Fällen wieder zu Schreib/Lese-Problemen führen. Kannst Du mir mal bitte, bitte schreiben wie ich ein solches Array (oder eine beliebige Variable) einfach Threadsicher machen kann. Damit würde es dann gehen. Das mit if(newMove) geht nicht, da die Variable nicht exestiert und wieder die Fehlermeldung kommt.
-
Gut, dass das mit den Arrays grundsätzlich gehen würde... ich habe nämlich keine Ahnung, was ich gemeint habe.
Habe nämlich irgendwie während dem Schreiben Array mit Thread verwechselt.
(Ich blamiere mich hier ja bloß noch...
) Aber du kannst die bool-Variablen auch in Arrays speichern.
Warum sollte es einen Schreib-/Lesefehler geben? Die bool-Variable (oder das Array
) sind ja ausserhalb des Threads deklariert.
Die Variable newMove ist doch da. Nur das Objekt dahinter wurde zerstört. Und das sollte man ja eben mit if(newMove) abfragen können.
-
Das mit if hat bei mir nicht geklappt, aber ich kann Morgen noch mal schauen. Bei Array kann ich Schwierigkeiten bekommen, wenn mein Ablauf einen neuen Bewegungsthread startet und gleichzeitig irgendjemand den NotAus drückt. Der NotAus-Thread würde im ungünstigen Fall auf das Array zugreifen (um alle Bewegungsthreads zu beenden), wenn gerade ein neuer Thread angelegt wird (Murphy).
-
Na eigentlich soll ja der NotAusThread nur auf sein eigenes "Feld" im Array (bzw. seine eigene "NotAusThreadLaeuft"-Variable) zugreifen. Alle anderen Threads machen das selbe. Dadurch bleibt der Inhalt der Variablen (Arrayinhalte) sehr nah an der tatsächlichen Existenz der Threads. So kann sich niemand so leicht dazwischenquetschen.
Um nochmal kurz zum try/catch zurückzukommen: Exceptions sind doch nicht böse. Wenn du auf einen Thread zugreifen willst, um ihn zu beenden, das aber nicht klappt, weil er gar nicht da ist, brauchst du ihn ja gar nicht beenden. Dann reicht es doch eigentlich, mit try/catch die Fehlermeldung zu unterdrücken.
-
Das mit der Exception kam mir nicht so wie ein elegater Weg vor (vielleicht falscher Ehrgeiz). Der NotAus-Thread macht bei mir nichts weiter als den Digitaleigang einer AD-Karte zu überwachen. Wird der NotAus-betätigt, werden alle Motoren augenblicklich gestopt und alle Bewegungsthreads beendet(Sonst könnte das zu einem ungewolltem Neuanlauf führen). Dafür braucht der NotAus-Thread aber Zugriff auf den Zustand aller anderen Threads. Daher das Schreib-Leseproblem. Er setzt dann alle Bewegungsthreads auf Terminate() und wartet noch ein paar Sekunden, damit alle Threads die Chance haben sich sauber zu beenden. Anschließend zeige ich ein Formular mit der Fehlermeldung an und fhr auf Referenzposition. Soweit geht ja auch alles, bis auf die Exception bei Thread beenden.
Kannst Du mir trotzdem schreiben wie man eine Variable vor gleichzeitigem Zugriff schützen kann? Wenns geht ein direktes Bsp für eine Variable 'temp', da ich davon keine Ahnung hab.
-
Andreas1333 schrieb:
Kannst Du mir trotzdem schreiben wie man eine Variable vor gleichzeitigem Zugriff schützen kann?
Nö. Hab ich behauptet, das zu können?
Könnte man meines Wissens nur mit einer weiteren Variablen lösen, die vor jedem Zugriff auf die Darf-nur-einmal-Zugreifen-Variable auf true und gleich danach wieder auf false gesetzt wird. Das muss man dann vor einem Zugriff nur abfragen. Aber wo brauchst du das? Bei deinem "Jemand drückt Notaus, während gerade ein neuer Thread erstellt wird" - Problem? Der neue Thread sollte doch dann trotzdem beim ersten Abfragen von Terminated (machst du doch, oder?) beendet werden? Hmm... nicht, wenn der Auftrag zum Instanziieren des erfolgt, NotAus gedrückt wird, alle aktiven Threads (der neue noch nicht) beendet werden und dann erst die Instanziierung des neuen Threads fertig wird. Stimmt, da ist ein Problem. Kannst ja nicht solange NotAus gedrückt ist jedem Thread das Beenden befehlen... oder doch?
-
1. Ist FreeOnTerminate=true oder false?
bei false: Solange Du von aussen nicht den Thread deletest, kannst Du auf die variable zugreifen.
2. Alle Threads (auser NotAus) sind gleiche Klasse?
:: mach eine static- Variable in den Header (public!!!)
:: Gib jedem Thread eine ID- Nre ( 1,2,4,8,...)
::in Konstruktor des Thread setzt Du das entsprechende Bit (= Thread erzeugt)
::in Destruktor resetzt Du das Bit (Thread zerstoert)
3. Ueber die static- Var kannst Du IMMER auf die Zustaende der Threads zugreifen. Das ist wie eine GEMEINSAME globale Variable.4. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Am Ende der Headerdatei musst Du die Variable initialisieren mit 0;5. Warten bis ein Thread Terminiert ist: siehe WaitFor()
6. Zugriff synchronisieren: siehe Synchronize()PS: Fuer jemand, der damit Geld verdient, fragst Du recht hilflos.
-
Erstmal hab ich das Problem jetzt mit Mutex gelöst. Beim Erstellen schreib ich so pro Thread eine Variable und beim Zerstören lösch ich diese wieder. Damit klappt alles Prima.
Mit Geld verdienen ist da übrigens nichts (Studienarbeit). Und woher weiß man alle diese Dinge? Bei mir ist das im Selbsstudium und das Thema Multithreading mit dem C++Builder wird in Büchern nicht gerade ausführlich erschlagen, also hab ich im Forum gefragt. Falls Du ein gutes Buch oder was anderes weißt, wo man das nachlesen , kennst kannst Du's ja mal posten.
-
Hi,
zum Thema Variablen threadsicher machen, solltest Du mal einen Blick auf TCriticalSection und TThreadList werfen.