net - create async method c#
¿Cómo ignorar las excepciones no observadas con async/await en MonoTouch? (1)
En versiones anteriores de MonoTouch, solía hacer esto para ignorar las excepciones no observadas:
TaskScheduler.UnobservedTaskException += delegate(object sender, UnobservedTaskExceptionEventArgs e) {
Console.WriteLine (e);
e.SetObserved ();
};
Si es una buena práctica es discutible, pero me gustaría saber si se logrará el mismo efecto con las palabras clave async
/ await ahora oficialmente admitidas en Xamarin.iOS 6.4 .
Aquí está el código que uso para probar:
async void OnClick (object sender, EventArgs e)
{
await Task.Run (() => { throw new Exception (); });
}
Cuando lo ejecuto, el depurador hace una pausa en AsyncVoidMethodBuilder
:
Leí que .NET 4.5 supuestamente cambió el comportamiento para que las excepciones no observadas no bloqueen la aplicación, pero esto no ayuda si las excepciones se publican en el contexto de sincronización de UIKit donde no puedo manejarlas.
¿Hay alguna forma de ignorar las excepciones no observadas de la await
en MonoTouch?
Este es el comportamiento correcto de los métodos async void
: se supone que deben generar la excepción en el SynchronizationContext
que estaba activo en el momento en que se inició el método async void
.
El cambio que mencionó en .NET 4.5 trata únicamente con excepciones de tareas no observadas y no se aplica a los métodos de async void
.
En el mundo (Microsoft) .NET, las diferentes implementaciones de SynchronizationContext
tienen un manejo de error de nivel superior diferente. WPF, WinForms y ASP.NET tienen diferentes maneras de manejar ese error, generalmente como parte de un tipo de Application
.
Miré a través de la API de UIKit de Mono, aunque no soy un usuario normal de Mono, y no pude encontrar ningún error de nivel superior en UIApplication
, y parece que UIKitSynchronizationContext
no es público (o al menos no está documentado).
Otra forma de ver este problema: el comportamiento de manejo de excepciones para los métodos de async void
está diseñado para ser exactamente igual que los manejadores de eventos (para más información, vea mi artículo de MSDN ). Entonces, puede responder la pregunta con otra pregunta: en UIKit, ¿cómo manejaría esta excepción?
void OnClick (object sender, EventArgs e)
{
throw new Exception();
}
async void
su excepción de async void
exactamente de la misma manera.
Alternativamente, si desea seguir usando UnobservedTaskException
, simplemente no puede observar la excepción de la tarea (en su código async void
, Task.Run
. Task.Run
devuelve una tarea que obtiene una excepción, y la está observando usando await
):
void OnClick (object sender, EventArgs e)
{
Task.Run(() => { throw new Exception(); });
}
Sin embargo, recomiendo usar async void
para los manejadores de eventos y (eventualmente) await
todas sus tareas. Esto asegurará que no obtenga ningún "error silencioso" (excepciones de tareas ignoradas) donde su programa simplemente deja de funcionar correctamente y usted no sabe por qué.