Warum Code in finally Block nicht ausgeführt wird?

8

Es scheint, dass Block schließlich nicht ausgeführt wird, wenn es anderen als Hauptthreadcode ausführt. Ist es möglich, die Ausführung in diesem Fall zu erzwingen?

Umgebung: VS 2010, .Net Framework 4.0.3

%Vor%

Aktualisierung:

Ich fand Erwähnungen und Erklärungen zu diesem Fall in MSDN:

ThreadAbortException-Klasse Ссылка

  

Wenn ein Aufruf an die Abort-Methode erfolgt, um einen Thread zu zerstören, wird der   Common Language Runtime löst eine ThreadAbortException aus.   ThreadAbortException ist eine spezielle Ausnahme, die abgefangen werden kann, aber es   wird automatisch am Ende des Catch-Blocks wieder ausgelöst. Wann   Diese Ausnahme wird ausgelöst. Die Laufzeitumgebung führt alle finally-Blöcke aus   bevor der Thread beendet wird . Weil der Thread ein unbegrenztes tun kann   Berechnung in den endgültig blockiert oder Thread.ResetAbort aufrufen, um abzubrechen   Beim Abbruch gibt es keine Garantie, dass der Thread jemals enden wird . Ob   Wenn Sie warten möchten, bis der abgebrochene Thread beendet ist, können Sie die   Thread.Join-Methode. Join ist ein blockierender Aufruf, der erst zurückkehrt   Der Thread stoppt die Ausführung tatsächlich.

Hinweis:

  

Wenn die Common Language Runtime (CLR) Hintergrundthreads nach beendet   Alle Vordergrund-Threads in einer verwalteten ausführbaren Datei sind beendet, dies jedoch nicht   Verwenden Sie Thread.Abort. Daher können Sie ThreadAbortException nicht verwenden   erkennen, wenn Hintergrund-Threads von der CLR beendet werden.

Vordergrund- und Hintergrund-Threads Ссылка

  

Wenn die Laufzeit einen Hintergrund-Thread stoppt, weil der Prozess heruntergefahren wird, wird keine Ausnahme im Thread ausgelöst. Wenn Threads jedoch angehalten werden, weil die AppDomain.Unload-Methode die Anwendungsdomäne entfernt, wird eine ThreadAbortException sowohl im Vordergrund als auch im Hintergrund ausgelöst.

Warum verwendet CLR am Ende der Anwendung nicht die AppDomain.Unload-Methode zum Entladen der Anwendungsdomäne vor dem Ende (Kill) des Hauptprozesses? Weil Ссылка :

  

Wenn ein Thread Unload aufruft, wird die Zieldomäne zum Entladen markiert.   Der dedizierte Thread versucht, die Domäne und alle darin enthaltenen Threads zu entladen   Die Domain wird abgebrochen. Wenn beispielsweise ein Thread nicht abbricht   weil es nicht verwalteten Code ausführt oder weil es a ausführt   endlich blockieren, dann nach einer gewissen Zeit a   CannotUnloadAppDomainException wird im ursprünglichen Thread ausgelöst   Unload genannt. Wenn der Thread, der schließlich nicht abgebrochen werden konnte   endet, wird die Zieldomäne nicht entladen. Daher im .NET Framework   Für die Version 2.0-Domäne wird nicht garantiert, zu entladen, da dies möglicherweise nicht der Fall ist   möglich sein, ausführende Threads zu beenden.

Fazit: In einigen Fällen muss ich überlegen, ob mein Code im Hintergrund- oder Vordergrund-Thread ausgeführt wird. Ist es möglich, dass mein Code nicht beendet wird, bevor der Anwendungs-Haupt-Thread alle Arbeit beendet?

    
Andir 13.03.2012, 07:29
quelle

2 Antworten

17

Ihr Code wird in einem Hintergrundthread ausgeführt. Wenn Sie AutoResetEvent festlegen, wird Ihr einzelner Vordergrund-Thread beendet (wenn Sie das Ende der Main -Methode erreichen), und der Prozess wird "sofort" abgebrochen.

Tatsächlich glaube ich, dass es wahrscheinlich ist, dass Ihr finally block ausgeführt wird, aber da Sie als erstes zwei Sekunden lang schlafen, wird der Prozess beendet, bevor er zu Ihrem WriteLine gelangt. ruf an.

Wenn Ihre Main -Methode noch immer ausgeführt wird oder ein anderer Vordergrund-Thread den Prozess am Leben erhält, sehen Sie Ihren finally -Block als normal. Dies ist nicht wirklich eine Frage von "endlich auf anderen Threads" - es ist eine Frage von "der Prozess bleibt nur am Leben, während es Vordergrund Threads gibt."

    
Jon Skeet 13.03.2012, 07:31
quelle
4

Sie können verhindern, dass die Hauptmethode beendet wird, bis die finally ausgeführt wurde. Es gibt viele mögliche Ansätze.

  • Sie können die Synchronisierung verwenden, um dies zu erreichen. Zum Beispiel mit einem ResetEvent, ähnlich dem, was Sie bereits tun, oder explizit einen Thread erstellen und sich diesem anschließen.

  • Sie könnten am Ende der Main -Methode nur einen einfachen Sleep oder eine Readline ausführen:

    %Vor%

Dann kann der Benutzer steuern, wann das Programm beendet wird.

  • Sie können einen Thread ohne Hintergrund anstelle eines Threads aus dem Thread-Pool verwenden. Dann wird das Programm nicht beendet, bis der Thread ebenfalls beendet wurde. Dies ist wahrscheinlich die beste und einfachste Option, wenn Sie Ihr Programm nicht beenden möchten, bis der Thread abgeschlossen ist.
Mark Byers 13.03.2012 07:32
quelle