1. ホーム
  2. c#

[解決済み] デッドロックを引き起こす非同期/awaitの例

2022-10-29 22:51:47

質問

私は、C#の非同期プログラミングのベストプラクティスに出会いました。 async / await というキーワードで検索してみてください(c# 5.0は初めてです)。

与えられたアドバイスの1つは、次のようなものでした。

安定性。同期のコンテキストを知る

... 同期コンテキストには、非リエントラントでシングルスレッドなものがあります。これは、与えられた時間にそのコンテキストで実行できる作業単位が 1 つだけであることを意味します。この例として、Windows UI スレッドや ASP.NET リクエスト コンテキストがあります。 これらのシングルスレッド同期コンテキストでは、簡単にデッドロックが発生します。シングルスレッド コンテキストからタスクを生成し、そのタスクをコンテキストで待機すると、待機中のコードがバックグラウンド タスクをブロックしてしまう可能性があります。

public ActionResult ActionAsync()
{
    // DEADLOCK: this blocks on the async task
    var data = GetDataAsync().Result;

    return View(data);
}

private async Task<string> GetDataAsync()
{
    // a very simple async method
    var result = await MyWebService.GetDataAsync();
    return result.ToString();
}

自分で分解しようとすると、メインスレッドがスポーンするのは MyWebService.GetDataAsync(); で結果を待ちますが、メインスレッドはそこで待ち構えているため GetDataAsync().Result . 一方、データの準備ができたとします。メインスレッドは継続ロジックを続け、文字列の結果を GetDataAsync() ?

なぜ上記の例でデッドロックが発生するのか、誰か説明してください。 何が問題なのか全く分かりません.

どのように解決するのですか?

を見てみましょう。 この例 をご覧ください。Stephenが明確な答えを持っています。

<ブロッククオート

つまりこれは、トップレベルのメソッドから始まって、( Button1_Click UI の場合 MyController.Get ASP.NETの場合)。

  1. トップレベルのメソッドが呼び出す GetJsonAsync (を呼び出します(UI/ASP.NETのコンテキスト内)。

  2. GetJsonAsync を呼び出すことで、REST リクエストを開始します。 HttpClient.GetStringAsync を呼び出すことでRESTリクエストを開始します (まだコンテキスト内)。

  3. GetStringAsync は、未完成の Task を返します。これは REST リクエストが完了していないことを示します。

  4. GetJsonAsync を待ちます。 Task が返す GetStringAsync . コンテキストはキャプチャされ、引き続き GetJsonAsync メソッドを後で実行し続けるために使われます。 GetJsonAsync は未完成の Task であることを示す GetJsonAsync メソッドが完全ではないことを示します。

  5. トップレベルのメソッドが同期的にブロックされ Task が返す GetJsonAsync . これはコンテキストスレッドをブロックします。

  6. ... 最終的に、RESTリクエストが完了します。これで Task によって返された GetStringAsync .

  7. の続きは GetJsonAsync は実行可能な状態になり、コンテキストが利用可能になるのを待ち、 コンテキストで実行できるようになります。

  8. デッドロック . トップレベルのメソッドはコンテクストスレッドをブロックし GetJsonAsync が完了するのを待ち、そして GetJsonAsync はコンテキストが解放され、完了するのを待っています。UI の例では、"context" は UI コンテキスト、ASP.NET の例では "context" は ASP.NET リクエスト コンテキストです。このタイプのデッドロックは、どちらの"context" でも発生する可能性があります。

もうひとつ、読んでおきたいリンクがあります。 待ち時間、UI、そしてデッドロック! なんと!