web-dev-qa-db-ja.com

HttpContext.Currentが待機後にヌルになるのはなぜですか?

私は次のテストWebAPIコードを持っています。本番環境ではWebAPIを使用しませんが、この質問に関する議論のために作成しました: WebAPI Async question

とにかく、問題のあるWebAPIメソッドは次のとおりです。

public async Task<string> Get(int id)
{
    var x = HttpContext.Current;
    if (x == null)
    {
        // not thrown
        throw new ArgumentException("HttpContext.Current is null");
    }

    await Task.Run(() => { Task.Delay(500); id = 3; });

    x = HttpContext.Current;
    if (x == null)
    {
        // thrown
        throw new ArgumentException("HttpContext.Current is null");
    }

    return "value";
}

awaitが完了すると、HttpContext.Currentは、スレッド静的変数として適切な値に解決されなくなります。さて、同期コンテキストに基づいて、待機後に実際に同じスレッドに戻ることを強制することができましたが、テストでは空想をしていません。これはawaitの単純で単純な使用法です。

別の質問のコメントで、HttpContext.Currentは、待ってから解決するはずです。この質問には、同じことを示す別のコメントもあります。それでは本当ですか?解決すべきですか?いいえと思いますが、asyncawaitは十分に新しいので、決定的なものを見つけることができないので、これに関する信頼できる答えが欲しいです。

TL; DR:HttpContext.Current潜在的にnullの後にawait

79
welegan

ASP.NET4.5アプリケーションを作成し、4.5をターゲットにしていることを確認してください。 asyncおよびawaitは、4.5およびで実行している場合を除き、ASP.NETで未定義の動作を持ち、新しい "タスクフレンドリーな」同期コンテキスト。

特に、これは次のいずれかを行う必要があることを意味します。

  • httpRuntime.targetFramework4.5に設定する、または
  • appSettingsで、aspnet:UseTaskFriendlySynchronizationContexttrueに設定します。

詳細は こちらから入手可能 です。

126
Stephen Cleary

@StephenClearyが正しく指摘したように、web.configでこれが必要です。

<httpRuntime targetFramework="4.5" />

最初にこれをトラブルシューティングするときに、上記のソリューション全体を検索し、すべてのWebプロジェクトに存在することを確認し、犯人としてすぐに却下しました。最終的に、これらの検索結果を完全なコンテキストで見ることになりました。

<!--
  For a description of web.config changes for .NET 4.5 see http://go.Microsoft.com/fwlink/?LinkId=235367.

  The following attributes can be set on the <httpRuntime> tag.
    <system.Web>
      <httpRuntime targetFramework="4.5" />
    </system.Web>
-->

ど.

レッスン:Webプロジェクトを4.5にアップグレードする場合、その設定を手動で適切に行う必要があります。

22
Todd Menier

私のテストに欠陥がありますか、それともここで欠落しているweb.config要素があり、それによりHttpContext.Currentが待機後に正しく解決されますか?

テストに欠陥はなく、待機後のHttpContext.Currentはnullであってはなりません。ASP.NETWeb APIでは待機するときに、これにより、この待機に続くコードに待機前に存在していた正しいHttpContextが渡されます。

3
Darin Dimitrov