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 asyncpode retornar void, Taskou 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 Taskmé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 voidmé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 awaiteditado:
Que tipos de métodos podem ser awaiteditados? Um método de retorno nulo pode ser awaiteditado?
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 GetAwaiterpode 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.
Taskmétodos de retorno podem produzir valores esperáveis. Prevemos que terceiros desejarão criar suas próprias implementações de Taskobjetos semelhantes que podem ser aguardados, e você poderá aguardá-los. No entanto, você não poderá declarar asyncmétodos que retornam nada void, exceto , Taskou 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.)