As respostas de SLaks e Killercam são boas; Eu pensei em adicionar um pouco mais de contexto.
Sua primeira pergunta é essencialmente sobre quais métodos podem ser marcados async
.
Um método marcado como async
pode retornar void
, Task
ou Task<T>
. Quais são as diferenças entre eles?
Um Task<T>
método assíncrono de retorno pode ser aguardado e, quando a tarefa for concluída, ele oferecerá um T.
Um Task
método assíncrono de retorno pode ser aguardado e, quando a tarefa for concluída, a continuação da tarefa está agendada para execução.
Um void
método assíncrono retornado não pode ser aguardado; é um método "dispare e esqueça". Funciona de forma assíncrona e você não tem como saber quando isso é feito. Isso é mais do que um pouco estranho; como o SLaks diz, normalmente você faria isso apenas ao criar um manipulador de eventos assíncrono. O evento é disparado, o manipulador é executado; ninguém vai "aguardar" a tarefa retornada pelo manipulador de eventos, porque os manipuladores de eventos não retornam tarefas e, mesmo retornando, que código usaria a tarefa para alguma coisa? Geralmente, não é o código do usuário que transfere o controle para o manipulador em primeiro lugar.
Sua segunda pergunta, em um comentário, é essencialmente sobre o que pode ser await
editado:
Que tipos de métodos podem ser await
editados? Um método de retorno nulo pode ser await
editado?
Não, um método de retorno nulo não pode ser aguardado. O compilador se traduz await M()
em uma chamada para M().GetAwaiter()
, onde GetAwaiter
pode ser um método de instância ou um método de extensão. O valor esperado deve ser aquele pelo qual você pode obter um garçom; claramente, um método de retorno nulo não produz um valor a partir do qual você pode obter um garçom.
Task
métodos de retorno podem produzir valores esperáveis. Prevemos que terceiros desejarão criar suas próprias implementações de Task
objetos semelhantes que podem ser aguardados, e você poderá aguardá-los. No entanto, você não poderá declarar async
métodos que retornam nada void
, exceto , Task
ou Task<T>
.
(ATUALIZAÇÃO: Minha última frase pode ser falsificada por uma versão futura do C #; existe uma proposta para permitir tipos de retorno diferentes dos tipos de tarefas para métodos assíncronos.)
(ATUALIZAÇÃO: o recurso mencionado acima chegou ao C # 7.)