Perché C # ti permette di eseguire un override asincrono?

14

In C #, quando si esegue l'override di un metodo, è consentito eseguire l'override async quando il metodo originale non lo era. Sembra una cattiva forma.

L'esempio che mi ha portato a questo è stato questo: sono stato coinvolto per risolvere un problema con il test del carico. In circa 500 utenti simultanei, il processo di accesso si interromperà in un ciclo di reindirizzamento. IIS registrava eccezioni con il messaggio "Un modulo asincrono o un handler completati mentre un'operazione asincrona era ancora in sospeso". Alcune ricerche mi hanno portato a pensare che qualcuno stesse abusando di async void , ma le mie ricerche rapide attraverso la fonte non hanno trovato nulla.

Purtroppo, stavo cercando 'async \ svoid' (regex search) quando avrei dovuto cercare qualcosa di simile a 'async \ s [^ T]' (supponendo che Task non fosse completamente qualificato ... ottieni il punto ).

Quello che ho scoperto successivamente era async override void onActionExecuting(... in un controller di base. Chiaramente quello doveva essere il problema, ed è stato. Risolvere il problema (rendendolo sincrono per il momento) ha risolto il problema.

Torna alla domanda: Perché oh, perché puoi contrassegnare un override come asincrono quando il codice chiamante non potrebbe mai aspettarlo?

    
posta Peter T. LaComb Jr. 05.03.2016 - 19:00
fonte

2 risposte

15

La async parola chiave consente al metodo di utilizzare la await sintassi all'interno della sua definizione. Posso await su qualsiasi metodo che restituisce un tipo Task indipendentemente dal fatto che si tratti di un metodo asincrono.

void è un tipo di ritorno legale (anche se scoraggiato ) per un metodo asincrono, quindi perché non dovrebbe essere permesso? Dall'esterno, async non abilita nulla di cui non potresti fare a meno. Il metodo con cui hai problemi potrebbe essere stato scritto per comportarsi esattamente allo stesso modo senza essere asincroni. La sua definizione sarebbe stata più prolissa.

Ai chiamanti, un metodo async T è un metodo normale che restituisce T (che è limitato a void , Task o Task<A> ). Che sia un metodo asincrono non fa parte dell'interfaccia. Si noti che il seguente codice è illegale:

interface IFoo {
    async void Bar();
}

Esso (o codice simile in una classe astratta) produce il seguente messaggio di errore in VS2012:

The 'async' modifier can only be used in methods that have a statement body

Se I ha inteso che un metodo in un'interfaccia o una classe genitore sia tipicamente asincrono, non posso usare async per comunicarlo. Se volessi implementarlo con la sintassi await , avrei bisogno di avere i metodi di override asincrono (nel caso della classe genitore).

    
risposta data 05.03.2016 - 20:41
fonte
10

L'unico scopo della parola chiave async è di attirare una parola chiave all'interno del corpo di quella funzione. Questo è necessario in modo che l'aggiunta della funzionalità di attesa non interrompesse il codice esistente. Microsoft ha deciso di avvalersi di attendere un'opzione di opt-in. Per una funzione che non è contrassegnata come asincrona, è possibile definire una variabile chiamata attesa senza problemi.

Quindi async non fa parte della firma di una funzione e non ha alcun significato semantico nel codice IL generato. È proprio lì che il compilatore sa come compilare correttamente la funzione. Indica inoltre al compilatore di garantire che solo Task, Attività < T > o viene restituito nulla.

    
risposta data 05.03.2016 - 23:43
fonte

Leggi altre domande sui tag