Ho seguito this question e ho compreso le ragioni alla base della risposta popolare (anche se non ancora accettata) da Peter Duniho. Specificamente, sono consapevole che non attesa di una successiva operazione di esecuzione prolungata bloccherà il thread UI:Dovrebbero essere attese operazioni annidate attendibili?
Il secondo esempio non cedere durante l'operazione asincrona. Invece, ottenendo il valore della proprietà content.Result, si forza il thread corrente ad attendere fino al completamento dell'operazione asincrona.
Ho anche confermato questo, per il mio vantaggio, in questo modo:
private async void button1_Click(object sender, EventArgs e)
{
var value1 = await Task.Run(async() =>
{
await Task.Delay(5000);
return "Hello";
});
//NOTE: this one is not awaited...
var value2 = Task.Run(async() =>
{
await Task.Delay(5000);
return value1.Substring(0, 3);
});
System.Diagnostics.Debug.Print(value2.Result); //thus, UI freezes here after 5000 ms.
}
Ma ora mi chiedo: cosa è necessario await
tutte le operazioni "awaitable" annidati all'interno di un awaitable più esterno operazione? Ad esempio, posso fare questo:
private async void button1_Click(object sender, EventArgs e)
{
var value0 = await Task.Run(() =>
{
var value1 = new Func<Task<string>>(async() =>
{
await Task.Delay(5000);
return "hello";
}).Invoke();
var value2 = new Func<string, Task<string>>(async (string x) =>
{
await Task.Delay(5000);
return x.Substring(0, 3);
}).Invoke(value1.Result);
return value2;
});
System.Diagnostics.Debug.Print(value0);
}
O posso fare questo:
private async void button1_Click(object sender, EventArgs e)
{
//This time the lambda is async...
var value0 = await Task.Run(async() =>
{
//we're awaiting here now...
var value1 = await new Func<Task<string>>(async() =>
{
await Task.Delay(5000);
return "hello";
}).Invoke();
//and we're awaiting here now, too...
var value2 = await new Func<string, Task<string>>(async (string x) =>
{
await Task.Delay(5000);
return x.Substring(0, 3);
}).Invoke(value1);
return value2;
});
System.Diagnostics.Debug.Print(value0);
}
e nessuno dei due congelare la UI. Quale è preferibile?
Sarei molto sorpreso se quelli tutti Stampa la stessa cosa, credo che si sta stampando un oggetto Task piuttosto che il suo risultato. –
@BenVoigt - No, bc in entrambi i casi l'attività viene scartata dal momento in cui è attesa. –
Ma uno di questi è il wrapping di una seconda attività. –