Wie eine Ausnahme in einem Hintergrundthread aus Beenden einer Anwendung zu verhindern?

stimmen
38

Ich kann hookup auf AppDomain.CurrentDomain.UnhandledExceptionAusnahmen von Hintergrund - Threads zu protokollieren, aber wie kann ich verhindern sie die Laufzeit endet?

Veröffentlicht am 09/10/2008 um 12:36
quelle vom benutzer
In anderen Sprachen...                            


5 antworten

stimmen
35

Zunächst sollten Sie wirklich versuchen, keine Ausnahmen geworfen zu haben - und nicht behandelt - in einem Hintergrundthread. Wenn Sie die Art und Weise Ihre Stellvertretung ausgeführt steuern, kapseln sie in einem Try-Catch-Block und einen Weg die Ausnahmeinformationen zurück zu Ihrem Haupt-Thread (mit EndInvoke, wenn Sie ausdrücklich BeginInvoke genannt, oder durch etwas gemeinsam genutzten Zustand irgendwo Aktualisierung) zu übergeben.

eine nicht behandelte Ausnahme ignorieren kann gefährlich sein. Wenn Sie eine echte un-handhabbare Ausnahme haben (OutOfMemoryException kommt in dem Sinn), gibt es nicht viel können Sie sowieso und Ihr Prozess zu tun ist grundsätzlich zum Scheitern verurteilt.

Zurück zu .Net 1.1, eine nicht behandelte Ausnahme in einem backgroundthread würde nur geworfen werden, um das Nichts und der Haupt-Thread würde gerne pflügen. Und das könnte böse Folgen haben. So in .Net 2.0 dieses Verhalten hat sich geändert.

Nun wird eine nicht behandelte Ausnahme in einem Thread geworfen, die nicht der Haupt-Thread ist, wird den Prozess beenden. Sie können darüber informiert werden (durch auf der AppDomain die Veranstaltung Anmeldung), aber der Prozess dennoch sterben.

Da dies unbequem sein kann (wenn Sie nicht wissen, was in dem Thread ausgeführt werden, und Sie sind nicht absolut sicher, dass es richtig bewacht, und Ihr Hauptthread muss elastisch sein), dann ist es eine Abhilfe. Es ist, als ein Vermächtnis Einstellungen bestimmt (das heißt, es ist dringend empfohlen, dass Sie sicherstellen, dass Sie nicht Streu Fäden haben), aber Sie können das frühere Verhalten auf diese Weise erzwingen:

Fügen Sie einfach diese Einstellung auf Ihre Service / application / was auch immer Konfigurationsdatei:

<configuration>
  <runtime>
    <!-- the following setting prevents the host from closing when an unhandled exception is thrown -->
    <legacyUnhandledExceptionPolicy enabled="1" />
  </runtime>
</configuration>

Es scheint nicht mit ASP.NET zu arbeiten, though.

Weitere Informationen (und eine große Warnung , dass diese Einstellung nicht in der kommenden Versionen des CLR unterstützt werden) siehe http://msdn.microsoft.com/en-us/library/ms228965.aspx

Beantwortet am 09/10/2008 um 12:44
quelle vom benutzer

stimmen
8

Von Joe Albahari ausgezeichneten Threading - Artikel:

Das .NET Framework stellt ein untergeordnetes Ereignis für die globale Ausnahmebehandlung: AppDomain.UnhandledException. Dieses Feuer-Ereignis, wenn es eine nicht behandelte Ausnahme in jedem Thread ist, und in jeder Art von Anwendung (mit oder ohne eine Benutzerschnittstelle). Doch während es einen guten letztinstanzliche Mechanismus für die Anmeldung nicht abgefangenen Ausnahmen bietet, stellt es kein Mittel zur Verhinderung der Anwendung von heruntergefahren - und keine Mittel, um den .NET nicht behandelte Ausnahme Dialog zu unterdrücken.

In Produktionsanwendungen wird ausdrücklich Ausnahmebehandlung auf allen Gewindeeingabemethoden erforderlich. Man kann die Arbeit schneiden einen Wrapper oder Helfer-Klasse unter Verwendung der Job, wie Background auszuführen (diskutiert in Teil 3).

Beantwortet am 09/10/2008 um 12:40
quelle vom benutzer

stimmen
4

Halten Sie die Antwort kurz gesagt, ja, Sie können die Laufzeit kündigt, verhindern.

Hier ist eine Demo der Lösung:

class Program
{
    void Run()
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Console.WriteLine("Press enter to exit.");

        do
        {
            (new Thread(delegate()
            {
                throw new ArgumentException("ha-ha");
            })).Start();

        } while (Console.ReadLine().Trim().ToLowerInvariant() == "x");


        Console.WriteLine("last good-bye");
    }

    int r = 0;

    void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Interlocked.Increment(ref r);
        Console.WriteLine("handled. {0}", r);
        Console.WriteLine("Terminating " + e.IsTerminating.ToString());

        Thread.CurrentThread.IsBackground = true;
        Thread.CurrentThread.Name = "Dead thread";            

        while (true)
            Thread.Sleep(TimeSpan.FromHours(1));
        //Process.GetCurrentProcess().Kill();
    }

    static void Main(string[] args)
    {
        Console.WriteLine("...");
        (new Program()).Run();
    }
}

Im Wesentlichen Sie einfach nicht lassen Sie die Laufzeit der zeigen „... Programm funktioniert nicht mehr“ Dialog.

Im Fall , dass Sie die Ausnahme und loggen leise Ausgang, können Sie anrufenProcess.GetCurrentProcess().Kill();

Beantwortet am 29/06/2009 um 05:38
quelle vom benutzer

stimmen
1

Hier ist eine große Blog - Post über dieses Problem: Umgang mit „Nicht behandelte Ausnahmen“ in .NET 2.0

IMO wäre es richtig, Ausnahmen in Hintergrund-Threads manuell zu handhaben und wieder werfen sie über Rückruf, wenn nötig.

delegate void ExceptionCallback(Exception ex);

void MyExceptionCallback(Exception ex)
{
   throw ex; // Handle/re-throw if necessary
}

void BackgroundThreadProc(Object obj)
{
   try 
   { 
     throw new Exception(); 
   }
   catch (Exception ex)
   { 
     this.BeginInvoke(new ExceptionCallback(MyExceptionCallback), ex); 
   }
}

private void Test()
{
   ThreadPool.QueueUserWorkItem(new WaitCallback(BackgroundThreadProc));
}
Beantwortet am 09/10/2008 um 12:51
quelle vom benutzer

stimmen
0
    AppDomain.CurrentDomain.UnhandledException += (sender, e2) =>
    {
        Thread.CurrentThread.Join();
    };

Aber Vorsicht, wird dieser Code einfrieren alle Stapelspeicher des Gewinde- und Threads verwaltete Objekt selbst. Allerdings, wenn Ihre Anwendung in bestimmten Zustand ist (kann sein, warf man LimitedDemoFunctionalityException oder OperationStopWithUserMessageException) und Sie entwickeln nicht 24/7 Anwendung funktioniert dieser Trick.

Schließlich glaube ich, MS sollte Entwickler erlauben, die Logik der nicht behandelte Ausnahmen von der Spitze des Stapels außer Kraft zu setzen.

Beantwortet am 24/12/2017 um 11:22
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more