Frage

Bearbeiten: Dies scheint ein Knackpunkt zu sein, also werde ich es einfach aus dem Weg rächen:

Ich benutze dies nicht für die Synchronisation. Einfach, um langlebige Aufgaben zu töten, wenn sie nicht mehr notwendig / wünschenswert werden.
Hypothetisch: Angenommen, diese Threads schreiben einfach in die Konsole (sagen wir: "Thread 1"), schlafen Sie eine zufällige Länge und beenden Sie dann. Wenn sie abgebrochen sind, möchte ich, dass sie mich mit einer anderen Konsole informieren (sagen wir: "Thread 1 abgebrochen"). Und ich möchte springen können gerade zum Abort -Code, wenn ich versuche, ihn vor dem Ausführen abzubrechen, ohne dass er seine normalen Funktionen ausführt. Wenn es während des normalen Funktionierens abgebrochen wird, druckt es natürlich beide.


Ich habe einen Teil von Threads, die ich in der Reihenfolge auf einer ASP-Site mit Visual Studio 2008 ausführen möchte (keine Ahnung, wie wichtig alles zählt, aber da ist es), und sie haben möglicherweise Code abgebrochen. das sollte ausgeführt werden, unabhängig davon, wie weit sie durch ihre Aufgabe sind. Also mache ich einen Thread wie diesen:

Thread t = new Thread(delegate() {
   try { 
      /* do things */ 
      System.Diagnostics.Debug.WriteLine("try");
   }
   catch (ThreadAbortException) {
      /* cleanup */ 
      System.Diagnostics.Debug.WriteLine("catch");
   }
});

Wenn ich nun den Teil der Threads abbrechen möchte, kann die Aufräumarbeiten später auf der ganzen Linie immer noch wünschenswert sein. Wenn Sie durch MSDN schauen, können Sie einen Thread, der nicht begonnen hat, und dann. Oder Sie können den abgebrochenen Faden darauf warten, dass er abgebrochen wird. Vermutlich können Sie sie kombinieren.

http://msdn.microsoft.com/en-us/library/ty8d3wta(v=vs.80).aspx
Um zu warten, bis ein Thread abgebrochen wurde, können Sie die Join -Methode auf dem Thread aufrufen, nachdem Sie die Ab -Abr -Methode aufgerufen haben. Es gibt jedoch keine Garantie dafür, dass das Warten endet.
Wenn Abort auf einen Thread gerufen wird, der nicht gestartet wurde, wird der Thread abgebrochen, wenn der Start aufgerufen wird. Wenn Abort auf einen Faden aufgerufen wird, der blockiert ist oder schläft, wird der Faden unterbrochen und dann abgebrochen.

Jetzt, wenn ich diesen Code debugge und durchstehe:

t.Abort(); // ThreadState == Unstarted | AbortRequested
t.Start(); // throws ThreadStartException: "Thread failed to start."
// so I comment it out, and
t.Join(); // throws ThreadStateException: "Thread has not been started."

Ich sehe zu keinem Zeitpunkt eine Ausgabe, noch brechen Blockpunkte auf dem Versuch oder dem Fangblock erreicht.
Seltsamerweise wird ThreadStartException nicht als möglicher Wurf von .start () von hier aus aufgeführt: http://msdn.microsoft.com/en-us/library/a9fyxz7d(v=vs.80).aspx (oder eine andere Version)

Ich verstehe, dass dies durch einen Startparameter vermieden werden könnte, in dem angegeben ist, ob der Thread auf Reinigungscode springen und auf den Abbruchanruf verzichten sollte (was wahrscheinlich das ist, was ich tun werde). Und ich könnte .Start () den Thread und dann .abort () es. Aber als unbestimmte Zeit kann ich zwischen .Start und .Abort verabschieden, und ich halte es für unzuverlässig, und die Dokumentation scheint zu sagen, dass meine ursprüngliche Methode funktionieren sollte.

Vermisse ich etwas? Ist die Dokumentation falsch?

Bearbeiten: ow. Und Sie können .Start (Param) nicht in einem nicht parametrisierten Thread (Start) anrufen. Gibt es eine Möglichkeit, herauszufinden, ob ein Thread abgesehen von Versuch und Irrtum parametrisiert ist oder nicht? Ich sehe einen privaten M_Delegate, aber nichts öffentlich ...

War es hilfreich?

Lösung

Beim Benutzen ...

t.Abort();
t.Start();

... Die Innerexception des ThreadStartExcpetion enthält die Threadabortexzeption, genau wie MSDN sagt: (Wenn Abort auf einen Thread gerufen wird, der nicht gestartet wurde, wird der Thread abbrechen, wenn der Start aufgerufen wird)

Wenn Sie ausführen ...

t.Start();
t.Abort();

... Die Threadabortexception kann nie auftreten, da der Thread keine Zeit hatte, bevor er abgebrochen wurde.

Wenn Sie so etwas wie ...

t.Start();
Thread.Sleep(100);
t.Abort();

... Der "Reinigungscode" sollte immer ausgeführt werden.

Wenn Sie den Reinigungscode ausführen müssen, auch wenn der Thread nichts erledigt hat, würde eine mögliche Lösung zusammen mit dem Abbruchanruf eine Reinigungsmethode starten.

Darüber hinaus sollten Sie versuchen, Threads abzubrechen und verschiedene Techniken zu verwenden (http://msdn.microsoft.com/en-us/library/ms228964.aspx)

Andere Tipps

Mir ist klar, was die Dokumentation Ihnen impliziert, aber das passiert nicht. Wenn Sie einen Thread abbrechen und dann beginnen, wird er niemals in irgendeiner Weise ausgeführt. Die CLR ist klug genug, um zu wissen, dass Thread-Aborts ein prekäres Geschäft sind, und eine Gelegenheit, die Ausführung des Threads insgesamt zu überspringen, ist daher nicht zu übersehen.

Vielleicht machen Sie Ihren Aufräumcode zu einer Unterprogramme. Wenn der übergeordnete Thread die Abbruch abbricht oder von sich aus weiß, ruft er den Reinigungscode explizit auf.

Denken Sie daran, dass .NETs Vorstellung, nach Abbruch eines Threads "aufzuräumen", die Appdomain der Baugruppen, die den abgebrochenen Thread auszuführen, entladen. Es ist eine andere Art zu sagen: "Erwarten Sie nicht, dass dies gut aufräumt." Sie sollten zuerst immer ein Design suchen, das keine abgebrochenen Fäden erfordert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top