1. ホーム
  2. c#

[解決済み] await vs Task.Wait - デッドロック?

2022-02-04 15:29:42

質問

との違いがよくわかりません。 Task.Waitawait .

ASP.NETのWebAPIサービスで、以下のような関数のようなものがあります。

public class TestController : ApiController
{
    public static async Task<string> Foo()
    {
        await Task.Delay(1).ConfigureAwait(false);
        return "";
    }

    public async static Task<string> Bar()
    {
        return await Foo();
    }

    public async static Task<string> Ros()
    {
        return await Bar();
    }

    // GET api/test
    public IEnumerable<string> Get()
    {
        Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());

        return new string[] { "value1", "value2" }; // This will never execute
    }
}

ここで Get はデッドロックになります。

何が原因なのでしょうか?なぜ、私がブロック待ちではなく await Task.Delay ?

解決方法は?

Waitawait - は、概念的には似ていますが、実際にはまったく異なるものです。

Wait はタスクが完了するまで同期的にブロックします。つまり、現在のスレッドは文字通りタスクの完了を待ってブロックされるのです。一般的なルールとして、"を使うべきです。 async でブロックしないことです。 async のコードを使用します。私のブログでは、詳細に踏み込んで 非同期コードでのブロッキングはデッドロックを引き起こすか .

await はタスクが完了するまで非同期で待機します。つまり、現在の メソッド は "paused"(その状態はキャプチャされます)であり、そのメソッドは呼び出し元に不完全なタスクを返します。その後 await 式が完了すると、メソッドの残りは継続としてスケジューリングされます。

また、quot;cooperative block"とありますが、これは、以下のようなタスクのことを指していると思われます。 Wait が待機中のスレッドで実行される可能性があります。このようなことが起こりうる状況もありますが、これは最適化です。このような状況はたくさんあります。 できない 例えば、そのタスクが別のスケジューラー用のものであったり、すでに開始されていたり、コードタスクでない場合(あなたのコードの例のような場合。 Wait を実行することはできません。 Delay タスクをインラインで実行するためのコードがないため)。

あなたは、私の async / await イントロ を参考にしました。