Domanda

Ho letto i post del blog di Eric Lippert sull'asincronia in C# 5 (Parte 4 Essere particolarmente rilevanti) e ho visto parlare Anders PDC10 sull'argomento e non sono chiaro su come le continue dai metodi asincroni vengono riprese in un unico contesto filettato.

Entrambe le fonti discutono dell'utilizzo di metodi asincroni in un singolo ciclo dell'interfaccia utente thread per migliorare la reattività e nell'esempio di Anders menziona che quando un'attività asincrona completa la sua continuazione è programmata dall'aggiunta di un messaggio alla pompa del messaggio.

Il metodo asincrono sa davvero che deve eseguire quella che sembra un'azione specifica di contesto o è stata una semplificazione?

Più in generale, come può riprendere i metodi asincroni gestiti in un singolo contesto filettato? Esiste un requisito per la pianificazione all'interno di un singolo thread?

È stato utile?

Soluzione

La continuazione dell'attività sa dove deve essere pianificata la continuazione - ad esempio "qualsiasi thread pool di thread" o "thread UI".

Questo comportamento è determinato dall'attesa ", tuttavia, in realtà non fa parte di ciò di cui è responsabile il compilatore C#. Il compilatore chiama solo BeginAwait e passa nella continuazione; L'attesa restituisce un valore booleano che indica se l'attività è già completata in modo sincrono o se il chiamante debba tornare e lasciare che la continuazione si verifichi in modo asincrono.

Quindi per il momento, quella decisione viene presa nell'attesa restituita da TaskEx - ma non sarei sorpreso di vedere tutto in bundle in Task infine. Ciò può fluire cose come il contesto di sincronizzazione, che sa come dovrebbero essere gestite ulteriori azioni.

Non sono del tutto sicuro di che tipo sinceramente contesto a thread singolo stai prendendo in considerazione ... o stai pensando a una situazione in cui la maggior parte del lavoro deve avvenire in un unico thread, ma altri thread possono essere coinvolti per il bit asincrono (ad esempio quando viene ricevuto un pacchetto HTTP , elaborato su un thread della porta di completamento IO e la risposta gestito di nuovo sul thread dell'interfaccia utente)?

Altri suggerimenti

La risposta di Jon è ovviamente fantastica; Pensavo di aggiungere solo un'altra cosa.

Prendi in considerazione un'applicazione Winforms con un singolo pulsante su un modulo che esegue il codice quando si fa clic sul pulsante.

Cosa succede quando lo sei non Fare clic sul pulsante? Niente. Il processo esiste, il codice è in esecuzione, ma non sembra fare nulla. In effetti quello che sta facendo è elaborare i messaggi sul thread dell'interfaccia utente e determinare che nessuno di loro è interessante, ma non sembra che stia facendo nulla di interessante.

Quando si fa clic sul pulsante, improvvisamente uno di quei messaggi è interessante e la pompa del messaggio sa che quando vede quell'evento di clic, dovrebbe eseguire del codice. Così lo fa.

Lo scenario asincronico-su-a-single-thread è lo stesso. La continuazione: il codice "cosa fare dopo l'attività è finito" è effettivamente un "gestore di eventi" dell'evento "Task is Finite". Quando l'attività termina, "spinge il pulsante" e accende un messaggio sulla coda del messaggio del thread dell'interfaccia utente. Non importa se lo fa dal thread dell'interfaccia utente o da un thread di completamento I/O o altro. Quando il thread dell'interfaccia utente arriva all'elaborazione di quel messaggio, invoca la continuazione. Proprio come quando il thread dell'interfaccia utente arriva per elaborare un pulsante Click, invoca il gestore del clic.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top