run - create async method c#
Atrapa excepciones no manejadas desde async (2)
Cuando un método async
que se espera al lanzar una excepción, la excepción se almacena en algún lugar y el lanzamiento se retrasa. En una aplicación WinForms o WPF, usa SynchronizationContext.Current
para publicar el lanzamiento de la excepción. Sin embargo, en, por ejemplo, una aplicación de consola, lanza la excepción en un grupo de subprocesos y desactiva la aplicación.
¿Cómo puedo evitar que las excepciones generadas por un método async
la aplicación?
EDITAR:
Aparentemente, el problema que estoy describiendo es porque tengo métodos async
void
. Ver comentarios.
¿Cómo puedo evitar que las excepciones generadas por un método asincrónico abran la aplicación?
Siga estas mejores prácticas:
- Todos los métodos
async
deben devolverTask
oTask<T>
menos que tengan que devolver unvoid
(por ejemplo, controladores de eventos). - En algún momento, debe
await
todas lasTask
devueltas desde los métodosasync
. La única razón por la que no querría hacer esto es si ya no le importa el resultado de la operación (p. Ej., Después de cancelarlo). - Si necesita capturar una excepción de un manejador de eventos de
async void
, cójala en el manejador de eventos, exactamente como lo haría si este fuera un código síncrono.
Puede encontrar útil mi post de introducción async
/ await
; También cubro varias otras mejores prácticas allí.
Cuando se inicia el método async
, captura el contexto de sincronización actual. Una forma de resolver este problema es crear su propio contexto de sincronización que capture la excepción.
El punto aquí es que el contexto de sincronización publica la devolución de llamada al grupo de subprocesos, pero con un try / catch a su alrededor:
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);
}
}
}
En la catch
anterior puede poner su lógica de manejo de excepciones.
A continuación, en cada subproceso ( SynchronizationContext.Current
es [ThreadStatic]
) donde desea ejecutar métodos async
con este mecanismo, debe configurar el contexto de sincronización actual:
SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());
El ejemplo Main
completo:
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");
}
}