web-dev-qa-db-ja.com

C#でステートメントとawaitキーワードの使用をうまくやる

asyncインスタンスを返すメソッドに対してIDisposable呼び出しを行っている状況があります。例えば:

HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://www.google.com"));

asyncが登場する前に、IDisposableインスタンスを操作する場合、「response」変数を使用したこの呼び出しとコードはusingステートメントでラップされます。

私の質問は、asyncキーワードがミックスでスローされたとき、それがまだ正しいアプローチであるかどうかです。コードはコンパイルされますが、usingステートメントは以下の両方の例で期待どおりに機能しますか?

例1

using(HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://www.google.com")))
{
    // Do something with the response

    return true;
}

例2

using(HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://www.google.com")))
{
    await this.responseLogger.LogResponseAsync(response);

    return true;
}
91
swingdoctor

はい、それは問題ないはずです。

最初の場合、あなたは本当に言っています:

  • 応答を取得できるまで非同期に待機します
  • 使用してすぐに廃棄する

2番目のケースでは、次のように言っています:

  • 応答を取得できるまで非同期に待機します
  • 応答を記録するまで非同期に待機します
  • 応答を破棄する

非同期メソッドのusingステートメントは「_odd」であり、Dispose呼び出しはリソースを取得したスレッドとは異なるスレッドで実行される可能性があります(同期コンテキストなどによって異なります)起こります...あなたが待っているものを仮定するとeverが現れるか、もちろん失敗します。 (Disposeステートメントに戻り値のないメソッドの呼び出しが含まれている場合、非同期コードでusingを呼び出すことにならないように。)

91
Jon Skeet