Freigeben über


asynchronousThreadAbort-MDA

Hinweis

Dieser Artikel gilt für das .NET Framework. Sie gilt nicht für neuere Implementierungen von .NET, einschließlich .NET 6 und höherer Versionen.

Der asynchronousThreadAbort-MDA (Managed Debugging Assistant, Assistent für verwaltetes Debuggen) wird aktiviert, wenn ein Thread versucht, einen asynchronen Abbruch in einem anderen Thread hervorzurufen. Der asynchronousThreadAbort-MDA wird nicht durch synchrone Threadabbrüche aktiviert.

Symptome

Eine Anwendung stürzt mit einer nicht behandelten ThreadAbortException ab, wenn der Thread der Hauptanwendung abgebrochen wird. Die Folgen der fortgesetzten Ausführung dieser Anwendung sind möglicherweise schwerwiegender als ein Absturz und können zur weiteren Beschädigung von Daten führen.

Als unteilbar konzipierte Vorgänge wurden wahrscheinlich nach der partiellen Fertigstellung unterbrochen. Dadurch befinden sich die Anwendungsdaten nun in einem nicht vorhersagbaren Zustand. Eine ThreadAbortException kann während der Ausführung von Programmcode an scheinbar zufälligen Stellen generiert werden, häufig auch an Stellen, an denen das Auslösen einer Ausnahme nicht zu erwarten war. Der Code ist möglicherweise nicht in der Lage, so eine Ausnahme zu behandeln. Dies führt zu einem fehlerhaften Zustand.

Die Symptome sind aufgrund der Zufälligkeit dieses Problems breit gefächert.

Ursache

Die Thread.Abort-Methode wurde aus dem Code in einem Thread für einen Zielthread aufgerufen, um einen asynchronen Threadabbruch hervorzurufen. Der Threadabbruch ist asynchron, da der die Abort-Methode aufrufende Code in einem anderen Thread ausgeführt wird als das Ziel des Abbruchvorgangs. Synchrone Threadabbrüche stellen in der Regel kein Problem dar, da ein Thread die Abort-Methode dabei nur an einem sicheren Anhaltepunkt aufrufen sollte, an dem sich die Anwendung in einem konsistenten Zustand befindet.

Asynchrone Threadabbrüche führen zu Problemen, da sie an nicht vorhersagbaren Stellen der Ausführung des Zielthreads verarbeitet werden. In einem Thread ausgeführter Code, der möglicherweise asynchron abgebrochen wird, müsste zum Vermeiden dieses Problems für jede einzelne Codezeile eine ThreadAbortException abfangen können, um dafür zu sorgen, dass die Anwendungsdaten anschließend in einem konsistenten Zustand vorliegen. Es ist jedoch unrealistisch zu erwarten, dass Code unter Berücksichtigung dieses Problems erstellt wurde, oder selbst Code zu verfassen, der Schutz vor allen möglichen Umständen bietet.

Aufrufe von nicht verwaltetem Code und von finally-Blöcken werden nicht asynchron abgebrochen, sondern sofort nach dem Verlassen einer dieser Kategorien.

Aufgrund des willkürlichen Auftretens dieses Problems ist die Ursache möglicherweise schwer zu ermitteln.

Lösung

Vermeiden Sie Codeentwürfe, die die Verwendung asynchroner Threadabbrüche erfordern. Es gibt mehrere besser geeignete Verfahren zum Unterbrechen eines Zielthreads, die keinen Aufruf von Abort erfordern. Am sichersten ist der Einsatz eines Mechanismus, z.B. eine gemeinsame Eigenschaft, mit der dem Zielprozess die Unterbrechungsanforderung signalisiert wird. Der Zielthread prüft an bestimmten sicheren Anhaltepunkten, ob das Signal übermittelt wurde. Wenn eine Unterbrechungsanforderung festgestellt wird, kann der Thread ordnungsgemäß beendet werden.

Auswirkungen auf die Laufzeit

Dieser MDA hat keine Auswirkungen auf die CLR. Es werden nur Angaben zu asynchronen Threadabbrüchen gemeldet.

Output

Der MDA meldet die ID des Threads, der den Abbruch durchführt, und die ID des Zielthreads für den Abbruch. Diese sind niemals gleich, da dieses Problem auf asynchrone Abbrüche beschränkt ist.

Konfiguration

<mdaConfig>
  <assistants>
    <asynchronousThreadAbort />
  </assistants>
</mdaConfig>

Beispiel

Zum Aktivieren des asynchronousThreadAbort-MDA genügt ein Aufruf von Abort für einen separaten laufenden Thread. Bedenken Sie die Folgen, wenn der Inhalt der Threadstartfunktion aus einer Reihe komplexerer Vorgänge bestehen würde, die an jedem beliebigen Punkt durch den Abbruch unterbrochen werden können.

using System.Threading;
void FireMda()
{
    Thread t = new Thread(delegate() { Thread.Sleep(1000); });
    t.Start();
    // The following line activates the MDA.
    t.Abort();
    t.Join();
}

Siehe auch