Encerre ou saia do método C# Async com “return”
-
21-12-2019 - |
Pergunta
Eu era novo no async-await
método em C# 5.0
, e tenho poucas perguntas em mente
Qual é a melhor maneira de escapar de um
async
método se falhou em um argumento de entrada ou verificação de nulo?Qual é o fluxo lógico de uso
return;
em uma tarefaasync
método (em algumas circunstâncias, tornou-se um loop infinito)?É
CancellationToken
ouTask.Yield
se encaixa melhor neste cenário?
public Func<AzureBlobInfo, string, Task> UploadSuccessCallBackAsync { get; set; }
private async Task OnUploadSuccessAsync(AzureBlobInfo info)
{
if (this.UploadSuccessCallBackAsync == null)
{
return;
}
var transactionType = this.FormData.Get("transactionType");
if (string.IsNullOrEmpty(transactionType))
{
transactionType = "unknown";
}
await this.UploadSuccessCallBackAsync(info, transactionType);
}
Solução
A melhor maneira de "falhar em algum problema" IMHO seria lançar a exceção apropriada, mas você pode definitivamente apenas usar return;
se preferir evitar exceções.
Isso criará uma tarefa concluída/com falha que foi concluída de forma síncrona, para que o chamador usando await
obterá uma tarefa concluída e continuará usando o mesmo thread.
CancellationToken
permite o chamador para cancelar a operação, o que não é o caso que você está descrevendo.Task.Yield
não encerra nenhuma operação, apenas permite que outras tarefas sejam executadas por algum tempo e se reagenda para mais tarde.
Outras dicas
Você pode retornar com segurança de um método assíncrono a qualquer momento.No seu caso (método que retorna uma tarefa), o compilador irá gerar uma tarefa encerrada, portanto, qualquer chamador que esteja aguardando sua função continuará.
Ao lançar uma exceção de um async
método, ele é capturado na tarefa para que não seja lançado até que a tarefa seja observada chamando Task.Wait()
, Task.Result
, aguardando a tarefa ou acessando o Exceptions
propriedade da tarefa.
Em termos de argumentos de entrada, uma maneira de contornar isso é dividir o método em duas partes, a primeira verifica os argumentos de entrada e depois chama o segundo método, que é async
.Ver esse perguntas respondidas por Stephen Cleary, por exemplo.Dessa forma, a exceção do argumento de entrada será lançada imediatamente fora da tarefa retornada pelo método.