Sé que generalmente se considera una mala idea usar async void
métodos de disparar y olvidar para iniciar tareas, porque no hay un seguimiento de la tarea pendiente y es complicado manejar las excepciones que pueden aparecer dentro de dicho método.
¿Debo evitar generalmente los async void
controladores de eventos también? Por ejemplo,
private async void Form_Load(object sender, System.EventArgs e)
{
await Task.Delay(2000); // do async work
// ...
}
Puedo reescribirlo así:
Task onFormLoadTask = null; // track the task, can implement cancellation
private void Form_Load(object sender, System.EventArgs e)
{
this.onFormLoadTask = OnFormLoadTaskAsync(sender, e);
}
private async Task OnFormLoadTaskAsync(object sender, System.EventArgs e)
{
await Task.Delay(2000); // do async work
// ...
}
¿Cuáles son las rocas submarinas para los controladores de eventos asíncronos, además de la posible reentrada?
Respuestas:
La pauta es evitar,
async void
excepto cuando se usa en un controlador de eventos, por lo que usarloasync void
en un controlador de eventos está bien.Dicho esto, por razones de pruebas unitarias , a menudo me gusta factorizar la lógica de todos los
async void
métodos. P.ej,fuente
Form_Load
el acceso apublic
? Parece que el código sería menos detallado de esa manera.OnFormLoadAsync
. Ahora veo que esto lo convierte en un truco útil. Gracias.Handled
bandera debe establecerse sincrónicamente; no se puede utilizarasync
para tomar una decisión sobre si el evento se gestiona o no.ICommand.Execute
métodoasync void
; Considero esto aceptable yaICommand.Execute
que lógicamente es un controlador de eventos.Generalmente, los controladores de eventos son el único caso en el que un método asincrónico vacío no es un olor a código potencial.
Ahora bien, si necesita realizar un seguimiento de la tarea por alguna razón, entonces la técnica que describe es perfectamente razonable.
fuente
Sí, generalmente el vacío asíncrono de controladores de eventos es el único caso. Si quieres saber más al respecto, puedes ver un gran video aquí en el canal 9.
The only case where this kind of fire-and-forget is appropriate is in top-level event-handlers. Every other async method in your code should return "async Task".
aquí está el enlace
fuente
Si usa ReSharper, una extensión recomendada gratuita podría serle útil. Analiza los métodos "async void" y resalta cuando se usan de manera inapropiada. La extensión puede distinguir diferentes usos de async void y proporcionar las correcciones rápidas apropiadas que se describen aquí: Wiki de extensión recomendada .
fuente