Acho que a verdade é ambígua até mesmo na documentação da Microsoft:
No Visual Studio 2012 e no .NET Framework 4.5, qualquer método que é atribuído com a async
palavra - chave ( Async
no Visual Basic) é considerado um método assíncrono, e os compiladores C # e Visual Basic realizam as transformações necessárias para implementar o método de forma assíncrona usando TAP. Um método assíncrono deve retornar um Task
ou um Task<TResult>
objeto.
http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx
Isso já não está certo. Qualquer método com async
é assíncrono e então diz que deve retornar um Task
ou Task<T>
- o que não é certo para métodos no topo de uma pilha de chamadas, Button_Click por exemplo, ou async void
.
Claro, você deve considerar qual é o objetivo da convenção?
Você poderia dizer que a Async
convenção de sufixo é para comunicar ao usuário da API que o método está aguardando. Para um método ser aguardado, ele deve retornar Task
para um void ou Task<T>
para um método de retorno de valor, o que significa que apenas o último pode ser sufixado com Async
.
Ou você pode dizer que a Async
convenção de sufixo é para comunicar que o método pode retornar imediatamente, renunciando ao thread atual para realizar outro trabalho e potencialmente causando corridas.
Esta citação de documento da Microsoft diz:
Por convenção, você anexa "Async" aos nomes dos métodos que têm um modificador Async ou async.
http://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_NamingConvention
O que nem mesmo menciona que seus próprios métodos assíncronos retornando Task
precisam do Async
sufixo, o que acho que todos concordamos que eles precisam.
Portanto, a resposta a essa pergunta poderia ser: ambos. Em ambos os casos, você precisa anexar Async
a métodos com async
palavra - chave e que retornam Task
ou Task<T>
.
Vou pedir a Stephen Toub que esclareça a situação.
Atualizar
Então eu fiz. E aqui está o que nosso bom homem escreveu:
Se um método público retornar uma tarefa e for assíncrono por natureza (ao contrário de um método que sempre executa de forma síncrona até a conclusão, mas ainda retorna uma tarefa por algum motivo), ele deve ter um sufixo “Async”. Essa é a diretriz. O objetivo principal aqui com a nomenclatura é tornar muito óbvio para um consumidor da funcionalidade que o método que está sendo chamado provavelmente não completará todo o seu trabalho de forma síncrona; é claro que também ajuda no caso em que a funcionalidade é exposta com métodos síncronos e assíncronos, de forma que você precisa de uma diferença de nome para distingui-los. Como o método atinge sua implementação assíncrona é irrelevante para a nomenclatura: se async / await é usado para obter a ajuda do compilador ou se os tipos e métodos de System.Threading.Tasks são usados diretamente (por exemplo, g. TaskCompletionSource) não importa, pois isso não afeta a assinatura do método no que diz respeito ao consumidor do método.
Claro, sempre há exceções a uma diretriz. O mais notável no caso de nomenclatura seriam os casos em que a razão de ser de todo um tipo é fornecer funcionalidade com foco assíncrono, caso em que ter Async em todos os métodos seria um exagero, por exemplo, os métodos na própria Tarefa que produzem outras Tarefas .
Quanto aos métodos assíncronos de retorno de vazio, não é desejável tê-los em uma área de superfície pública, uma vez que o chamador não tem uma boa maneira de saber quando o trabalho assíncrono foi concluído. Se você precisar expor publicamente um método assíncrono de retorno vazio, provavelmente deseja ter um nome que transmita que o trabalho assíncrono está sendo iniciado e poderá usar o sufixo “Async” aqui, se fizer sentido. Dado o quão raro esse caso deve ser, eu diria que é realmente uma decisão caso a caso.
Espero que ajude, Steve
A orientação sucinta da frase inicial de Stephen é bastante clara. Ele exclui async void
porque é incomum querer criar uma API pública com esse design, pois a maneira correta de implementar um vazio assíncrono é retornar uma Task
instância simples e deixar o compilador fazer sua mágica. No entanto, se você quiser um public async void
, Async
é aconselhável anexar . Outros async void
métodos do topo da pilha , como manipuladores de eventos, geralmente não são públicos e não importam / qualificam.
Para mim, isso me diz que, se eu me perguntar sobre como sufocar Async
em um async void
, provavelmente devo transformá-lo em um async Task
para que os chamadores possam aguardar e, em seguida, anexar Async
.