web-dev-qa-db-ja.com

非同期ラムダを待つことはできません

このことを考慮、

Task task = new Task (async () =>{
    await TaskEx.Delay(1000);
});
task.Start();
task.Wait(); 

Task.Wait()の呼び出しはタスクの完了を待たず、次の行がすぐに実行されますが、非同期ラムダ式をメソッド呼び出しにラップすると、コードは期待どおりに機能します。

private static async Task AwaitableMethod()
{
    await TaskEx.Delay(1000);    
}

その後(svickからのコメントに応じて更新)

await AwaitableMethod(); 
61
kennyzx

ラムダの例では、task.Wait()を呼び出すとき、返される遅延タスクではなく、構築した新しいタスクを待機しています。希望の遅延を得るには、結果のタスクも待つ必要があります。

Task<Task> task = new Task<Task>(async () => {
    await Task.Delay(1000);
});
task.Start();
task.Wait(); 
task.Result.Wait();

新しいタスクの作成を避け、2つのタスクの代わりに1つのタスクを処理するだけで済みます。

Func<Task> task = async () => {
    await TaskEx.Delay(1000);
};
task().Wait();
82
Joe Daley

TaskEx.RunExを使用する必要があります。

内部で内部タスクを待機することにより、asyncTaskPoolメソッドの実行をネイティブにサポートします。そうしないと、直面している問題が発生し、外側のタスクのみが待機し、明らかにすぐに完了し、待機する必要のあるタスクが残るか、場合によっては(さらに悪いことに)できないボイドラムダが残ります待った。

または、外側のタスクを正しく構築していれば(現在はそうではありません)、タスクを2回待つことができます。

現在のコード(修正済み):

Task task = new Task<Task>(async () =>{
    await TaskEx.Delay(1000);
});

task.Start();
var innerTask = await task;
await innerTask;

TaskEx.RunExを使用:

Task task = TaskEx.RunEx(async () =>{ // Framework awaits your lambda internally.
    await TaskEx.Delay(1000);
});

await task;
6