Em que cenários alguém gostaria de usar
public async Task AsyncMethod(int num)
ao invés de
public async void AsyncMethod(int num)
O único cenário em que consigo pensar é se você precisa da tarefa para acompanhar seu progresso.
Além disso, no método a seguir, são assíncronas e aguardam palavras-chave desnecessárias?
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}
c#
asynchronous
.net-4.5
user981225
fonte
fonte
Foo()
se tornariaFooAsync()
.Thread.Sleep
com suas tarefas você deveawait Task.Delay(num)
em vezTask.Delay
não éTask.AsyncDelay
como todos os métodos da tarefa são assíncronosasync void
alternativaasync Task
. O método travou porque estava usando um objeto de contexto do Entity Framework declarado como membro do controlador antes que o método fosse executado. A estrutura descartou o controlador antes que seu método fosse executado. Mudei o método para assíncrono de tarefas e funcionou.Respostas:
1) Normalmente, você gostaria de retornar a
Task
. A principal exceção deve ser quando você precisa ter umvoid
tipo de retorno (para eventos). Se não há motivo para não permitir que o chamador sejaawait
sua tarefa, por que não?2) os
async
métodos que retornamvoid
são especiais em outro aspecto: eles representam operações assíncronas de nível superior e têm regras adicionais que entram em jogo quando sua tarefa retorna uma exceção. A maneira mais fácil é mostrar a diferença com um exemplo:f
A exceção de sempre é "observada". Uma exceção que deixa um método assíncrono de nível superior é simplesmente tratada como qualquer outra exceção não tratada.g
A exceção de nunca é observada. Quando o coletor de lixo vem para limpar a tarefa, ele vê que a tarefa resultou em uma exceção e ninguém tratou da exceção. Quando isso acontece, oTaskScheduler.UnobservedTaskException
manipulador é executado. Você nunca deve deixar isso acontecer. Para usar seu exemplo,Sim, use
async
eawait
aqui, eles garantem que seu método ainda funcione corretamente se uma exceção for lançada.para obter mais informações, consulte: http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
fonte
f
vez deg
no meu comentário. A exceção def
é passada para oSynchronizationContext
.g
aumentaráUnobservedTaskException
, masUTE
não interromperá mais o processo se não for tratado. Há algumas situações em que é aceitável ter "exceções assíncronas" como essa que são ignoradas.WhenAny
váriosTask
s resultando em exceções. Muitas vezes, você só precisa lidar com o primeiro e muitas vezes deseja ignorar os outros.WhenAny
em primeiro lugar para ignorar as outras exceções. , com ou sem uma exceção.Encontrei este artigo muito útil sobre
async
evoid
escrito por Jérôme Laban: https://jaylee.org/archive/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void .htmlA linha inferior é que um
async+void
pode travar o sistema e geralmente deve ser usado apenas nos manipuladores de eventos do lado da interface do usuário.fonte
Eu tive uma ideia clara dessas declarações.
Exceções de um método de vácuo assíncrono não podem ser capturadas com captura
Essas exceções podem ser observadas usando AppDomain.UnhandledException ou um evento abrangente para aplicativos GUI / ASP.NET, mas o uso desses eventos para o tratamento regular de exceções é uma receita para a impossibilidade de manutenção (ele trava o aplicativo).
Os métodos de vácuo assíncrono têm diferentes semânticas de composição. Os métodos assíncronos que retornam Tarefa ou Tarefa podem ser facilmente compostos usando Aguardar, Task.WhenAny, Task.WhenAll e assim por diante. Os métodos assíncronos que retornam nulo não fornecem uma maneira fácil de notificar o código de chamada que eles concluíram. É fácil iniciar vários métodos de cancelamento assíncrono, mas não é fácil determinar quando eles terminaram. Os métodos Async void notificarão seu SynchronizationContext quando iniciarem e terminarem, mas um SynchronizationContext personalizado é uma solução complexa para código de aplicativo comum.
O método Async Void é útil ao usar o manipulador de eventos síncronos, porque eles geram suas exceções diretamente no SynchronizationContext, que é semelhante ao comportamento dos manipuladores de eventos síncronos
Para obter mais detalhes, consulte este link https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
fonte
O problema de chamar async void é que você nem recebe a tarefa de volta; não há como saber quando a tarefa da função foi concluída (consulte https://blogs.msdn.microsoft.com/oldnewthing/20170720-00/ ? p = 96655 )
Aqui estão as três maneiras de chamar uma função assíncrona:
fonte
Acho que você também pode usar
async void
para iniciar operações em segundo plano, desde que tenha cuidado para capturar exceções. Pensamentos?fonte
Minha resposta é simples, você não pode esperar método nulo
Portanto, se o método for assíncrono, é melhor aguardar, pois você pode perder a vantagem assíncrona.
fonte
De acordo com a documentação da Microsoft , NUNCA deve usar
async void
fonte