2013-04-18 6 views
9

In Steven Toub's article:Unbeobachtete Task-Ausnahmen in .NET 4.5 noch Absturz App

Um es einfacher für Entwickler asynchronen Code auf Aufgaben basierend zu schreiben, .NET 4.5 ändert das Standardausnahmeverhalten für unbeobachtete Ausnahmen. Während unbeobachtete Exceptions immer noch das UnobservedTaskException-Ereignis auslösen (dies wäre jedoch eine breaking change), stürzt der Prozess standardmäßig nicht ab. Stattdessen wird die Ausnahme gegessen werden, nachdem das Ereignis ausgelöst wird, unabhängig davon, ob ein Ereignishandler die Ausnahme beobachtet.

Aber das Ergebnis meines Experiments stimmt nicht mit der obigen Aussage überein. Unten ist mein Code:

static void Main(string[] args) 
{ 
    DownloadAsync("http://an.invalid.url.com); 
} 

async static void DownloadAsync(string url) 
{ 
    using (var client = new System.Net.Http.HttpClient()) 
    { 
     string text = await client.GetStringAsync(url); 
     Console.WriteLine("Downloaded {0} chars", text.Length); 
    } 
} 

Da ich eine ungültige URL DownloadAsync()-Methode übergeben, wird der Anruf an HttpClient ‚s GetStringAsync() Methode eine expcetion werfen, und stürzt die Anwendung.

Meine Frage ist also: Stört nicht unbeobachtete Ausnahmen in .NET 4.5 immer noch App standardmäßig?

+4

Es ist nicht unbeobachtet, ist eine implizite Warte die text.length erreichbar. – Jesse

+1

@Jesse Ist es nicht die Zuweisung des Ergebnisses zu 'text', die bewirkt, dass das Ergebnis beobachtet wird, anstatt die spätere Verwendung von' text.Length'? –

+2

@MatthewWatson Sie sind völlig richtig, in meinen Gedanken war es eine Aufgabe, aber natürlich ist es nicht. – Jesse

Antwort

22

Sie haben eine Task mit einer Ausnahme (die von GetStringAsync zurückgegebene). Jedoch beobachtet die await die Task Ausnahme, die sich dann aus der DownloadAsync-Methode (die async void ist) fortpflanzt.

Ausnahmen, die sich aus async void Methoden entwickeln, verhalten sich anders; Sie werden auf die SynchronizationContext ausgelöst, die aktiv war, als die async void-Methode gestartet wurde (in diesem Fall ein Threadpool SynchronizationContext). Dies ist nicht als unbeobachtete Ausnahme betrachtet.

Wenn Sie DownloadAsync ändern Task zurückkehren, dann werden Sie eine tatsächliche unbeobachtet Task Ausnahme haben, die (richtig) werden ignoriert:

static void Main(string[] args) 
{ 
    DownloadAsync("http://an.invalid.url.com); 
    Console.ReadKey(); 
} 

async static Task DownloadAsync(string url) 
{ 
    using (var client = new System.Net.Http.HttpClient()) 
    { 
    string text = await client.GetStringAsync(url); 
    Console.WriteLine("Downloaded {0} chars", text.Length); 
    } 
} 
+0

Super Antwort! Vielen Dank! –

+1

@ StephenCleary: Sehr informativ! Das ist nicht etwas, auf das Sie jeden Tag stoßen, deshalb bin ich neugierig, wo Sie auf solch ein tiefgehendes Wissen über diesen speziellen Mechanismus gestoßen sind. Möchten Sie das Buch oder den Artikel teilen? – Anthony

+1

@Anthony: .NET-Reflektor, viele Fragen (meist in MSDN-Foren) und jahrelange Experimente. Ich schreibe gerade * ein Buch. :) –