Quando viene avviato il metodo async
, acquisisce il contesto di sincronizzazione corrente. Un modo per risolvere questo problema è creare il proprio contesto di sincronizzazione che cattura l'eccezione.
Il punto qui è che il contesto messaggi di sincronizzazione della richiamata al pool di thread, ma con un try/catch intorno ad esso:
public class AsyncSynchronizationContext : SynchronizationContext
{
public override void Send(SendOrPostCallback d, object state)
{
try
{
d(state);
}
catch (Exception ex)
{
// Put your exception handling logic here.
Console.WriteLine(ex.Message);
}
}
public override void Post(SendOrPostCallback d, object state)
{
try
{
d(state);
}
catch (Exception ex)
{
// Put your exception handling logic here.
Console.WriteLine(ex.Message);
}
}
}
Nella catch
sopra di voi può mettere la logica di gestione delle eccezioni.
Avanti, su ogni filo (SynchronizationContext.Current
è [ThreadStatic]
) in cui si desidera eseguire async
metodi con questo meccanismo, è necessario impostare il contesto di sincronizzazione corrente:
SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());
La completa Main
esempio:
class Program
{
static void Main(string[] args)
{
SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());
ExecuteAsyncMethod();
Console.ReadKey();
}
private static async void ExecuteAsyncMethod()
{
await AsyncMethod();
}
private static async Task AsyncMethod()
{
throw new Exception("Exception from async");
}
}
fonte
2012-09-07 08:25:53
Se è in attesa un metodo asincrono, l'eccezione viene generata nel codice che la attende. Le eccezioni non gestite si comportano in questo modo solo se il metodo è "void' return. Questo è un motivo per evitare di usare il metodo 'async void' il più possibile. – svick
I metodi @svick 'async void' determinano un comportamento deterministico; chiamare una funzione 'Task'-return che genera un'eccezione e non attende l'attività solleverà l'evento' UnobservedTaskException' in un punto semirandom in futuro quando gira il garbage collector, e se non fa nulla, lascia che il programma continui silenziosamente come se va tutto bene Il problema non è con i metodi 'async void', ma espongono semplicemente il vero problema. Se * non * richiami una funzione di 'Task'-return da un metodo' async', ci sono buone probabilità che tu stia facendo qualcosa di sbagliato. – hvd
A proposito, solo "buone probabilità" perché ci sono alcuni casi eccezionali (non puniti) in cui va bene scartare le eccezioni, ma non molto. – hvd