Por que o C # permite fazer uma substituição assíncrona?


16

Em C #, quando você substitui um método, é permitido fazer a substituição assíncrona quando o método original não era. Parece uma forma ruim.

O exemplo que me trouxe a isso foi o seguinte: fui chamado para ajudar com um problema de teste de carga. Em cerca de 500 usuários simultâneos, o processo de login seria interrompido em um loop de redirecionamento. O IIS registrava exceções com a mensagem "Um módulo ou manipulador assíncrono concluído enquanto uma operação assíncrona ainda estava pendente". Algumas pesquisas me levaram a pensar que alguém estava abusando async void, mas minhas pesquisas rápidas na fonte não encontraram nada.

Infelizmente, eu estava procurando por 'async \ svoid' (pesquisa regex) quando deveria estar procurando algo mais como 'async \ s [^ T]' (assumindo que a tarefa não estava totalmente qualificada ... você entendeu).

O que eu encontrei mais tarde foi async override void onActionExecuting(...em um controlador base. Claramente, esse tinha que ser o problema, e era. Corrigir isso (tornando-o síncrono no momento) resolveu o problema.

Voltando à pergunta: Por que, oh, por que você pode marcar uma substituição como assíncrona quando o código de chamada nunca poderia aguardá-la?



O que exatamente inibe um chamador a aguardar o método substituído? Não vejo obstáculo.
Martin Maat

@ MartinMaat Você pode aguardar apenas métodos que retornam Task.
Derek Elkins saiu de SE

Talvez esse seja um ponto interessante que eu não havia notado. Eu precisaria verificar, mas não recordo o aviso do VS sobre a invocação de métodos não assíncronos sem aguardar.
Peter T. LaComb Jr. /

Respostas:


16

A palavra - chave async permite que o método use a awaitsintaxe dentro de sua definição. Eu posso awaitem qualquer método que retorne um Tasktipo, independentemente de ser um método assíncrono.

voidé um tipo de retorno legal (embora desanimado ) para um método assíncrono; por que não seria permitido? Do lado de fora, asyncnão está permitindo nada que você não possa fazer sem ele. O método com o qual você está tendo problemas poderia ter sido escrito para se comportar exatamente da mesma maneira sem ser assíncrono. Sua definição teria sido mais detalhada.

Para os chamadores, um async Tmétodo é um método normal que os retornos T(que se limita a void, Taskou Task<A>). O fato de ser um método assíncrono não faz parte da interface. Observe que o seguinte código é ilegal:

interface IFoo {
    async void Bar();
}

Ele (ou código semelhante em uma classe abstrata) produz a seguinte mensagem de erro no VS2012:

O modificador 'async' pode ser usado apenas em métodos que possuem um corpo de instrução

Se eu fiz pretendem um método em uma classe de interface ou pai para ser tipicamente assíncrona, eu não posso usar asyncpara se comunicar isso. Se eu quisesse implementá-lo com a awaitsintaxe, seria necessário ter métodos de substituição assíncrona (no caso da classe pai).


1
Você não menciona overridenada, mas é disso que se trata.
Nathan Tuggy

4
@NathanTuggy O ponto principal da resposta é que asyncnão muda a interface de um método, apenas o que é sintaticamente permitido em sua definição; portanto, se é uma substituição ou não, é completamente irrelevante.
Derek Elkins saiu de SE

1
Por favor, explique isso, em vez de supor que todos já sabem tudo de relevante.
Nathan Tuggy

2
@ NathanTuggy Eu sinto que expliquei isso. Você pode fazer uma pergunta específica sobre a qual está confuso ou imagina que outra pessoa confusa perguntaria? A única coisa que posso acrescentar é ressaltar que o asyncmodificador pode ser aplicado apenas a implementações. Você não pode declarar um método assíncrono em uma interface, por exemplo, sublinhando que se um método é assíncrono ou não não faz parte da interface.
Derek Elkins saiu de SE

5
Coloque a explicação na resposta , quero dizer. Não é para isso que servem os comentários a longo prazo.
precisa

10

O único objetivo da palavra-chave assíncrona é tornar a palavra-chave no corpo dessa função. Isso é necessário para que a adição da funcionalidade de espera não quebre o código existente. A Microsoft decidiu fazer uso de aguardar uma opção de aceitação. Para uma função que não está marcada como assíncrona, você pode definir uma variável chamada aguardar sem nenhum problema.

Portanto, async não faz parte da assinatura de uma função e não tem significado semântico no código IL gerado. Está estritamente presente para o compilador saber como compilar corretamente a função. Ele também instrui o compilador a garantir que apenas Tarefa, Tarefa <T> ou nula esteja sendo retornada.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.