Perché C # ti consente di eseguire una sostituzione asincrona?


16

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

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

Purtroppo stavo cercando "async \ svoid" (ricerca regex) quando avrei dovuto cercare qualcosa di più simile a "async \ s [^ T]" (supponendo che Task non fosse pienamente qualificato ... capisci il punto).

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

Torna alla domanda: perché oh perché puoi contrassegnare una sostituzione come asincrona quando il codice chiamante non potrebbe mai aspettarlo?



Cosa impedisce esattamente a un chiamante di attendere il metodo ignorato? Non vedo alcun ostacolo.
Martin Maat,

@MartinMaat Puoi solo attendere i metodi che ritornano Task.
Derek Elkins lasciò SE

Forse è un bel punto che non avevo notato. Dovrei controllare, ma non ricordo l'avvertimento VS sull'invocazione di metodi non asincroni senza attendere.
Peter T. LaComb Jr.

Risposte:


16

La parola chiave asincrona consente al metodo di utilizzare la awaitsintassi all'interno della sua definizione. Posso awaitsu qualsiasi metodo che restituisce un Tasktipo indipendentemente dal fatto che si tratti di un metodo asincrono.

voidè un tipo di restituzione legale (sebbene scoraggiato ) per un metodo asincrono, quindi perché non dovrebbe essere consentito? Dall'esterno, asyncnon sta abilitando 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 asincrono. La sua definizione sarebbe stata solo più dettagliata.

Ai chiamanti, un async Tmetodo è un metodo normale che ritorni T(che è limitata a void, Tasko Task<A>). Che si tratti di un metodo asincrono non fa parte dell'interfaccia. Si noti che il seguente codice è illegale:

interface IFoo {
    async void Bar();
}

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

Il modificatore 'asincrono' può essere utilizzato solo nei metodi che hanno un corpo di istruzione

Se volevo che un metodo in un'interfaccia o in una classe genitore fosse tipicamente asincrono, non potrei usarlo asyncper comunicarlo. Se volessi implementarlo con la awaitsintassi, avrei bisogno di avere metodi di override asincroni (nel caso della classe genitore).


1
Non menzionate overrideaffatto, ma è di questo che si tratta.
Nathan Tuggy,

4
@NathanTuggy Il punto centrale della risposta è che asyncnon cambia l'interfaccia di un metodo, solo ciò che è sintatticamente consentito nella sua definizione, quindi che si tratti di una sostituzione o meno è completamente irrilevante.
Derek Elkins lasciò SE

1
Per favore, spiegalo , piuttosto che supporre che tutti sappiano già tutto ciò che è rilevante.
Nathan Tuggy,

2
@NathanTuggy Sento di averlo spiegato. Puoi fare una domanda specifica sulla quale sei confuso o immagini che potrebbe fare un'altra persona confusa? L'unica cosa che posso pensare di aggiungere è sottolineare che il asyncmodificatore può essere applicato solo alle implementazioni. Non è possibile dichiarare un metodo asincrono in un'interfaccia, ad esempio, sottolineando che se un metodo è asincrono o meno non fa parte dell'interfaccia.
Derek Elkins lasciò SE

5
Metti la spiegazione nella risposta , intendo. Non è questo il motivo per cui i commenti sono a lungo termine.
Nathan Tuggy,

10

L'unico scopo della parola chiave asincrona è rendere una parola chiave attesa nel corpo di quella funzione. Ciò è necessario affinché l'aggiunta della funzionalità wait non abbia interrotto il codice esistente. Microsoft ha deciso di fare uso di wait un'opzione di opt-in. Per una funzione non contrassegnata come asincrona è possibile definire senza problemi una variabile denominata waitit.

Quindi asincrono non fa parte della firma di una funzione e non ha alcun significato semantico nel codice IL generato. È strettamente lì per il compilatore sapere come compilare correttamente la funzione. Indica inoltre al compilatore di assicurarsi che venga restituito solo Task, Task <T> o vuoto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.