Como posso esperar que um void async
método termine seu trabalho?
por exemplo, eu tenho uma função como abaixo:
async void LoadBlahBlah()
{
await blah();
...
}
agora quero ter certeza de que tudo foi carregado antes de continuar em outro lugar.
c#
asynchronous
MBZ
fonte
fonte
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
await Task.Run(() => blah())
é enganoso. Isso não espera a conclusão da função assíncronablah
, apenas a criação (trivial) da tarefa e continua imediatamente antes dablah()
conclusão.Thread.Sleep
não é assíncrono. Esta questão é sobre aguardar umaasync void
função, digamosasync void blah() { Task.Delay(10000); }
Se você pode alterar a assinatura de sua função para,
async Task
então você pode usar o código apresentado aquifonte
A melhor solução é usar
async Task
. Você deve evitarasync void
por vários motivos, um dos quais é a composição.Se o método não puder ser retornado
Task
(por exemplo, é um manipulador de eventos), você poderá usarSemaphoreSlim
o sinal do método quando ele estiver prestes a sair. Considere fazer isso em umfinally
bloco.fonte
faça um AutoResetEvent, chame a função e aguarde AutoResetEvent e defina-o dentro de async void quando você souber que está pronto.
Você também pode aguardar uma tarefa que retorne do seu vazio assíncrono
fonte
Você realmente não precisa fazer nada manualmente, a
await
palavra-chave pausa a execução da função atéblah()
retornar.T
é o tipo de objetoblah()
retornadoVocê não pode realmente
await
umavoid
função, entãoLoadBlahBlah()
não pode servoid
fonte
LoadBlahBlah()
terminar, nãoblah()
Eu sei que essa é uma pergunta antiga, mas ainda é um problema que eu continuo abordando, e ainda não há uma solução clara para fazer isso corretamente ao usar async / waitit em um método de assinatura assíncrona de void.
No entanto, notei que .Wait () está funcionando corretamente dentro do método void.
e como async void e void têm a mesma assinatura, você pode precisar fazer o seguinte.
Confundidamente, async / waitit não é bloqueado no próximo código.
Quando você descompila seu código, meu palpite é que o async void cria uma tarefa interna (assim como a tarefa assíncrona), mas como a assinatura não suporta retornar essas tarefas internas
isso significa que internamente o método de async void ainda poderá "aguardar" os métodos de async internamente. mas externamente incapaz de saber quando a tarefa interna está concluída.
Portanto, minha conclusão é que o async void está funcionando conforme o esperado e, se você precisar de feedback da tarefa interna, precisará usar a assinatura da tarefa assíncrona.
espero que minhas divagações façam sentido para quem também procura respostas.
Edit: Eu criei um código de exemplo e o descompilei para ver o que realmente está acontecendo.
Se transforma em (editar: eu sei que o código do corpo não está aqui, mas nas máquinas de estado, mas as máquinas de estado eram basicamente idênticas, então eu não me incomodei em adicioná-las)
nem o AsyncVoidMethodBuilder nem o AsyncTaskMethodBuilder têm realmente qualquer código no método Start que indique a sua obstrução e sempre será executado de forma assíncrona após o início.
significando sem a tarefa retornada, não haveria maneira de verificar se ela está completa.
conforme o esperado, ele inicia apenas a tarefa executando assíncrona e continua no código. e a tarefa assíncrona, primeiro ela inicia a tarefa e depois a devolve.
então acho que minha resposta seria nunca usar o async void, se você precisar saber quando a tarefa está concluída, é para isso que serve a tarefa assíncrona.
fonte