Podążałem za this question i rozumiem powody tej popularnej (aczkolwiek nieuznanej) odpowiedzi przez Peter Duniho. W szczególności, to sobie sprawę, że nie oczekujących na kolejne długotrwała praca blokuje nić ui:Czy należy zagnieżdżać oczekiwane operacje?
Drugi przykład nie daje w asynchronicznej. Zamiast tego, pobierając wartość właściwości content.Result, zmuszasz bieżący wątek do oczekiwania na zakończenie operacji asynchronicznej.
Mam jeszcze potwierdził to, dla własnej korzyści, tak jak poniżej:
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.
}
Ale teraz zastanawiam się: czy trzeba await
wszystko „awaitable” operacji zagnieżdżonych wewnątrz najbardziej zewnętrznej awaitable operacja? Na przykład, mogę to zrobić:
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);
}
Można zrobić to:
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);
}
i żadna z nich zamrozić UI. Który z nich jest lepszy?
Byłbym bardzo zaskoczony, gdyby ci wszyscy wydrukować to samo, wierzę, że ktoś drukuje obiekt Task zamiast jego wyniku. –
@BenVoigt - Nie, bc w obu przypadkach zadanie jest rozpakowywane, ponieważ jest oczekiwane. –
Ale jednym z nich jest owijanie drugiego zadania. –