Eu sei que geralmente é considerado uma má ideia usar async void
métodos de disparar e esquecer para iniciar tarefas, porque não há controle da tarefa pendente e é complicado lidar com exceções que podem ser lançadas dentro de tal método.
Em geral, devo evitar async void
manipuladores de eventos também? Por exemplo,
private async void Form_Load(object sender, System.EventArgs e)
{
await Task.Delay(2000); // do async work
// ...
}
Posso reescrever assim:
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
// ...
}
Quais são as rochas subaquáticas para manipuladores de eventos assíncronos, além da possível reentrância?
Respostas:
A diretriz é evitar,
async void
exceto quando usado em um manipulador de eventos, portanto, usarasync void
em um manipulador de eventos está OK.Dito isso, por motivos de teste de unidade , geralmente gosto de fatorar a lógica de todos os
async void
métodos. Por exemplo,fonte
Form_Load
o acessopublic
? Parece que o código seria menos detalhado dessa forma.OnFormLoadAsync
. Vejo agora que isso é um truque útil. Obrigado.Handled
sinalizador deve ser definido de forma síncrona; não é possível usarasync
para tomar uma decisão sobre se o evento é tratado ou não.ICommand.Execute
métodoasync void
; Eu considero isso aceitável, poisICommand.Execute
é logicamente um manipulador de eventos.Geralmente, os manipuladores de eventos são o único caso em que um método void async não é um cheiro de código potencial.
Agora, se você precisa rastrear a tarefa por algum motivo, a técnica que você descreve é perfeitamente razoável.
fonte
Sim, geralmente assíncrono sem manipuladores de eventos é o único caso. Se quiser saber mais sobre isso, assista a um ótimo vídeo aqui no 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".
aqui está o link
fonte
Se você usa o ReSharper, uma extensão ReCommended gratuita pode ser útil para você. Ele analisa os métodos de "vazio assíncrono" e realça quando usado de forma inadequada. A extensão pode distinguir diferentes usos de void assíncrono e fornecer soluções rápidas apropriadas descritas aqui: wiki ReCommended-Extension .
fonte