2013-04-18 15 views
9

In Steven Toub's article:inosservato eccezioni Task a .NET 4.5 ancora app incidente

Per rendere più facile per gli sviluppatori di scrivere codice asincrono basato su Attività, .NET 4.5 cambia il comportamento di default per eccezione inosservati eccezioni. Mentre le eccezioni inosservate causano comunque l'evento UnobservedTaskException da sollevare (non farlo sarebbe una modifica di interruzione ), il processo non si arresterà in modo anomalo per impostazione predefinita. Piuttosto, l'eccezione finirà per essere mangiata dopo che l'evento è stato innalzato, indipendentemente dal fatto che un gestore di eventi osservi l'eccezione.

Ma il risultato del mio esperimento non corrisponde alla dichiarazione di cui sopra. Qui di seguito è il mio codice:

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); 
    } 
} 

Dato che mi passa un URL non valido per DownloadAsync() metodo, la chiamata al metodo di HttpClient s' GetStringAsync() genera un expcetion, e si blocca l'applicazione.

Quindi la mia domanda è: le eccezioni inosservate in .NET 4.5 continuano ad arrestare l'app per impostazione predefinita?

+4

E 'non inosservato, l'accesso alla text.length è un'attesa implicita. – Jesse

+1

@Jesse Non è l'assegnazione del risultato a 'text' che fa sì che il risultato sia osservato, piuttosto che l'uso successivo di' text.Length'? –

+2

@MatthewWatson hai perfettamente ragione, nella mia mente era un compito ma ovviamente non lo è. – Jesse

risposta

22

Si dispone di un Task con un'eccezione (quella restituita da GetStringAsync). Tuttavia, await sta osservando l'eccezione Task, che quindi si propaga dal metodo DownloadAsync (che è async void).

Le eccezioni di propagazione dei metodi async void si comportano in modo diverso; vengono generati su SynchronizationContext attivo quando è stato avviato il metodo async void (in questo caso, un pool di thread SynchronizationContext). Questo è non considerato un'eccezione non osservata.

Se si cambia DownloadAsync tornare Task, allora si avrà un'eccezione inosservata Task vero e proprio, che verrà ignorato (correttamente):

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

Risposta eccezionale! Grazie! –

+1

@StephenCleary: molto informativo! Questo non è qualcosa che incontri ogni giorno, quindi sono curioso di sapere dove ti sei imbattuto in una conoscenza così approfondita di questo particolare meccanismo. Vuoi condividere il libro o l'articolo? – Anthony

+1

@Anthony: reflector .NET, molte domande (principalmente sui forum MSDN) e anni di sperimentazione. Sono, tuttavia, attualmente * scrivendo * un libro. :) –

Problemi correlati