esegue l'attività due volte? O lanciare un'eccezione perché ha già già eseguito?
No e no. L'unica cosa che await
fa è chiamare il numero Task.GetAwaiter
, non causa l'esecuzione di alcunché. Se l'attività è già stata eseguita fino al completamento, estrarrà il valore se è un Task<T>
o eseguirà in modo sincrono la riga successiva se è un Task
, poiché esiste un ottimizzazione per le attività già completate.
Un semplice demo:
async Task Main()
{
var foo = FooAsync();
await foo;
await foo;
var bar = BarAsync();
var firstResult = await bar;
var secondResult = await bar;
Console.WriteLine(firstResult);
Console.WriteLine(secondResult);
}
public async Task FooAsync()
{
await Task.Delay(1);
}
public async Task<int> BarAsync()
{
await Task.Delay(1);
return 1;
}
Se si drill-down per la macchina dello Stato in sé, vedrete questo:
this.<foo>5__1 = this.<>4__this.FooAsync();
taskAwaiter = this.<foo>5__1.GetAwaiter();
if (!taskAwaiter.IsCompleted)
{
this.<>1__state = 0;
this.<>u__1 = taskAwaiter;
M.<FooBar>d__0 <FooBar>d__ = this;
this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter, M.<FooBar>d__0>
(ref taskAwaiter, ref <FooBar>d__);
return;
}
Questa ottimizzazione controlla innanzitutto il completamento del compito. Se l'attività non è completa, chiamerà UnsafeOnCompleted
che registrerà la continuazione. Se è completa, si rompe il switch
e va a:
this.<>1__state = -2;
this.<>t__builder.SetResult();
che definisce il risultato per il sottostante Task
, e in questo modo che effettivamente ottenere il valore in modo sincrono.
fonte
2015-09-07 08:44:48
Perché non ci provi? Non è difficile da testare. – Enigmativity
L'intuizione chiave da avere qui è che * attendere non esegue un'attività *. Await * attende in modo asincrono l'esecuzione di un'attività *. Da qui il nome "attendi". C'è un mito persistente che attende l'inizio di un compito, ma ovviamente non lo fa; hai già un compito iniziato in mano quando lo aspetti. –
Il vero occhio per me è stato il concetto di "continuazioni". Penso che senza questa intuizione, è difficile capire "attendere". – Sentinel