2016-06-14 11 views
5

Próbuję ustalić, dlaczego moja aplikacja konsolowa nie została zerwana przez nieobsługiwany wyjątek zadania. Wszystko, co robię, to utworzyć zadanie, w którym natychmiast zgłaszam wyjątek. Wreszcie wymuszam GC. W pierwszym przykładzie mam program obsługi zdarzenia TaskScheduler.UnobservedTaskException i widzę, że wyjątek zostanie obsłużony.Aplikacja konsoli nie została zerwana przez nieobsługiwany wyjątek zadania.

static async Task ThrowsException() 
{ 
    Console.WriteLine("Throwing!"); 
    throw new Exception("Test exception"); 
} 

static void Main(string[] args) 
{ 
    TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; 
    ThrowsException(); 
    Console.WriteLine("Collecting garbage."); 
    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 
    Console.WriteLine("Done collecting garbage."); 
    Console.ReadKey(); 
} 

static void TaskScheduler_UnobservedTaskException(object sender, 
    UnobservedTaskExceptionEventArgs e) 
{ 
    Console.WriteLine("Unobserved task exception occured in finalizer."); 
    Console.WriteLine(e.Exception.InnerException.Message); 
} 

wyjściowa:

Throwing! 
Collecting garbage. 
Unobserved task exception occured in finalizer. 
Test exception 
Done collecting garbage. 

Ale gdybym wykomentuj linię TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException program nadal działa do końca. W tym przypadku wyjście jest:

Throwing! 
Collecting garbage. 
Done collecting garbage. 

Dlaczego nie katastrofa zastosowanie w tym przypadku?

Odpowiedz

4

Niezniszczenie programu z niezaobserwowanego wyjątku zadania było zmianą, która została wykonana dla .NET 4.5, patrz remarks section of the MSDN for the event. Jeśli chcesz, aby program mają pre .NET 4.5 zachowanie i spowodować awarię trzeba umieścić w app.config

<configuration> 
    <runtime> 
     <ThrowUnobservedTaskExceptions enabled="true"/> 
    </runtime> 
</configuration> 

Spowoduje to powrót starych zachowań.

0

Wyjątek ThrowsException jest metodą asynchroniczną i dlatego jeśli nie będziesz czekać na tę metodę, wyjątek zostanie połknięty.
Zakładam, że trzeba zadzwonić to metoda tak:

ThrowsException.Wait(); 

Albo nawet złapać wyjątek:

try 
{ 
    ThrowsException().Wait(); 
} 
catch (AggregateException e) 
{ 
    // Do something 
} 

Również przeczytaniu poniższego pomoże Ci zrozumieć, dlaczego nie crash zgłoszenie: TaskScheduler.UnobservedTaskException Event.

Powiązane problemy