without run method espaƱol ejemplos create await async c# .net async-await unhandled-exception

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:

  1. Todos los métodos async deben devolver Task o Task<T> menos que tengan que devolver un void (por ejemplo, controladores de eventos).
  2. En algún momento, debe await todas las Task devueltas desde los métodos async . 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).
  3. 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"); } }