2017-10-23 1 views
0

Ich habe ein Problem zu entscheiden, was in dieser Situation zu tun ist, möchte ich einen abgetrennten Thread haben, aber immer noch in der Lage sein, für den Fall, dass ich es vorzeitig abbrechen möchte , vermutlich bevor ich eine neue Instanz davon starte, um sicherzustellen, dass der Thread immer noch nicht auf Dinge zugreift, wenn dies nicht der Fall ist.Einen Thread beenden, der verbunden oder dereferenziert werden könnte

Dies bedeutet, dass ich es nach dem Aufruf den Faden rechts nicht lösen sollte, so ist, dann habe ich ein paar Optionen:

  • Selbst lösen den Faden, wenn er das Ende seiner Ausführung ist erreicht, aber dann wouldn‘ t dies verursacht Probleme, wenn ich versuche, es aus dem Hauptthread zu verbinden? Dies wäre meine bevorzugte Lösung, wenn das Problem, es zu verbinden, nachdem es sich selbst gelöst hat, gelöst werden könnte. Ich könnte den Thread-Handle, auf den der Haupt-Thread Zugriff hat, von dem selbst ablösenden Thread dereferenzieren, bevor ich ihn selbst loslöse. Wenn der Haupt-Thread jedoch versucht, direkt vor der Dereferenzierung des Handle-Threads beizutreten, kann dies zu Problemen führen , also müsste ich die Dereferenzierung im Thread schützen und wie auch immer (ich weiß nicht wie, muss ich vielleicht eine Variable erstellen, um dies anzuzeigen) Ich würde prüfen, ob ich dem Hauptthread mit einem Mutex beitreten soll, der kompliziert die Dinge. Irgendwie habe ich das Gefühl, dass dies nicht der richtige Weg ist.
  • Lass den Faden hängen, bis ich ihn schließe, was lange dauern kann, je nachdem, wie ich Dinge organisiere, könnte es nicht sein, bevor ich loslasse, was er gemacht hat (zB den Faden vor dem Freigeben eines Bildes verbinden) das wurde vom Thread geladen/verarbeitet, wenn ich es nicht mehr brauche)
  • Lassen Sie die Hauptthread regelmäßig abfragen, wenn der Thread seine Arbeit erledigt hat, dann treten Sie ihm bei (oder trennen Sie es tatsächlich) und geben Sie an, es nicht zu versuchen wieder beitreten?
  • Oder sollte ich nur pthread_exit() aus dem Thread anrufen, aber was ist, wenn ich versuche, es zu verbinden?

Wenn ich ein bisschen verwirrt bin, ist es, weil ich bin. Ich schreibe in C99 mit TinyCThread, einem einfachen Wrapper für Pthread und Win32-API-Threading. Ich bin nicht einmal sicher, wie meine Thread-Handles dereferenziert werden, unter Windows ist der Thread-Handle HANDLE, und das Festlegen eines Handle auf NULL scheint es zu tun, ich bin mir nicht sicher, ob es der richtige Weg ist, es mit dem pthread_t-Typ zu machen.

Epilog: Basierend auf John Bollinger ‚s Antwort, die ich mit Abnehmen des Thread gehen wählte, die meisten von diesem Thread des Codes in einem Mutex setzen, auf diese Weise, wenn ein anderer Thread, bis der Faden blockieren will praktisch es getan wird, kann benutze diesen Mutex.

Antwort

1

Der Preis für die Verwendung einer Abstraktionsschicht wie TinyCThreads ist, dass Sie sich nur auf die definierten Merkmale der Abstraktion verlassen können. Sowohl Windows als auch POSIX bieten Funktionen und Details, die nicht unbedingt von TinyCThreads übernommen werden. Auf der anderen Seite kann dies dazu führen, dass Sie sich auf eine festere Grundlage verlassen, als Sie andernfalls mit Hilfe implementierungsspezifischer Funktionen zusammenhacken könnten.

Wie auch immer, sagen Sie,

ich ein freistehendes Gewinde haben wollen, aber noch in der Lage sein, es ich bei beitreten wollen es früh abbrechen,

aber das ist inkonsistent. Sobald Sie einen Thread lösen, können Sie ihm nicht beitreten. Ich vermute, du meintest etwas mehr wie "Ich möchte einen Thread, dem ich beitreten kann, solange er läuft, aber dass ich nicht beitreten muss, wenn er beendet wird." Das ist zumindest konsequent, aber es konzentriert sich auf den Mechanismus.

Was ich denke, Sie eigentlich wollen würde besser als ein Thread beschrieben, die Sie synchron abbrechen können, solange es ausgeführt wird, aber dass Sie sonst nicht beitreten müssen, wenn es beendet. Ich stelle jedoch fest, dass die ganze Idee einen Weg voraussetzt, den Thread vorzeitig beenden zu lassen, und es scheint nicht, dass TinyCThread dafür eine eingebaute Möglichkeit bietet. Es wird auch ein Mechanismus benötigt, um zu bestimmen, ob ein bestimmter Thread noch am Leben ist, und TinyCThread bietet dies auch nicht an.

Als Erstes benötigen Sie einen zusätzlichen gemeinsamen Status pro Thread, der den Thread-Status verfolgt (Ausführen/Abbrechen angefordert/beendet). Da der Status geteilt wird, benötigen Sie einen Mutex, um ihn zu schützen, und das muss wahrscheinlich auch per-Thread sein. Um ferner zu ermöglichen, dass ein Thread (z. B. der Haupt-Thread) darauf wartet, dass sich dieser Zustand ändert, wenn er einen Thread abbricht, wird eine Variable pro Thread-Bedingung benötigt.

Damit kann sich der neue Thread selbst ablösen, er muss jedoch regelmäßig prüfen, ob ein Abbruch angefordert wurde. Wenn der Thread seine Arbeit beendet, entweder weil er einen Abbruch festgestellt hat oder weil er das normale Ende seiner Arbeit erreicht hat, führt er die erforderliche Bereinigung durch, setzt den Status auf "beendet", sendet an den CV und beendet ihn.

Jeder Thread, der einen anderen Thread abbrechen möchte, sperrt den zugehörigen Mutex und überprüft, ob der Thread bereits beendet ist. Wenn nicht, setzt es den Thread-Status auf "Abbruch angefordert" und wartet auf die Bedingungsvariable, bis der Status "beendet" wird. Bei Bedarf können Sie eine zeitgesteuerte Wartezeit verwenden, um der Abbruchanforderung eine Zeitüberschreitung zu ermöglichen. Nach dem erfolgreichen Abbrechen des Threads kann es möglich sein, die Mutex-, CV- und Shared-Variablen zu bereinigen.

Ich merke, dass all dies hängt von meiner Interpretation Ihrer Anfrage ab, und insbesondere von der Aussicht, dass das, wonach Sie suchen, ist das Abbrechen/Abbrechen von Threads. Keine der Alternativen, die Sie auf den Weg gebracht haben, scheinen das anzugehen; zum größten Teil sie geben Sie den unerwünschten Thread ab, der Ihrem ausgedrückten Interesse nicht dient, es zu verhindern, unerwünschte Änderungen zum geteilten Staat zu machen.

+0

Sie haben Recht. Also ich möchte in der Lage sein, einen Thread abzubrechen und darauf zu warten, dass es vorbei ist, bevor ich fortfahre, ein Mutex ist eine gute Idee. Die Art und Weise, wie ich es aktuell mache, ist, dass ich einen Zeiger auf eine Struktur an meinen Thread weitergebe, der unter anderem ein 'volatile int abort'-Element enthält, das den Thread anweist, seine Schleifen zu stoppen. Da die Hauptfunktion nur schreibt und der Thread nur liest und beide Operationen effektiv atomar sind (wir ändern hier nur ein Bit) brauche ich keinen Mutex dafür. Sie haben auch Recht, dass mir der Rückgabewert egal ist. –

+0

Sie sind falsch, @MichelRouzic. Eine "volatile" Variable hat nicht die von Ihnen benötigte Semantik. Sie könnten eine Variable mit * atomic * -Typ verwenden, aber ich bin mir nicht sicher, ob MSVC das unterstützt, zumindest mit C11-Syntax. In jedem Fall brauchen Sie einen Lebenslauf, und deshalb brauchen Sie einen Mutex, also die ganze Frage von "volatile" * vs *. Atom * vs *. Vanille ist strittig. –

+0

Also sollte ich den Thread vom Start lösen, den größten Teil seines Codes in einen Mutex legen, dann im Hauptthread sollte ich meine abort-Variable setzen und dann versuchen, den Mutex zu sperren (dann entsperren Sie ihn sofort), was den Hauptblock blockieren würde thread bis der Thread ziemlich fertig ist, richtig? Es scheint tatsächlich eine ziemlich elegante Lösung zu sein, danke! Ich denke, eigentlich konnte ich den Haupt-Thread nicht blockieren und eine zweite Instanz des Threads starten, der Mutex würde die zweite Instanz blockieren, bis die erste Instanz ihren Mutex entsperrt, was sogar noch besser sein könnte. –

0

Es ist mir nicht klar, was Sie wollen, aber Sie können eine Bedingungsvariable verwenden, um grundsätzlich beliebige Verbindungssemantik für Threads zu implementieren. Die POSIX Rationale enthält ein Beispiel dafür, wie man pthread_join mit einem Timeout implementiert (Suche nach timed_thread).

Verwandte Themen