ASP.NETの上に構築されたさまざまなWebサービス用のかなり大きな既存のコードベースがあり、そのコードはアクセスを多用しますHttpContext.Current.User
( としてラップされます)。これは、アンビエントスコープを提供するためにClient.User
内部的に使用されると確信しています。[ThreadStatic]
の形式でより多くの非同期コードを使用し始める可能性があるかどうかを現在調べていますが、 の使用がこれにどのように適合するasync/await
かを見つけるのに苦労しています。[ThreadStatic]
頻繁に使用されるため、依存を取り除くこと[ThreadStatic]
は実際には不可能です。
await
がヒットすると、コードの実行がそこで停止し、呼び出しがすぐに返され、非同期コードが返されたときに実行を継続するように継続が設定されていることを理解しています。一方、元のスレッドは、別の要求を処理するなど、他の用途に自由に使用できます。ここまでは私の理解です。
決定的な答えが本当に見つからないHttpContext.Current.User
のは、 が の前後で同じであることが保証されているかどうかawait
です。
だから基本的に:
HttpContext.Current.User = new MyPrincipal();
var user = HttpContext.Current.User;
await Task.Delay(30000);
// Meanwhile, while we wait for that lots of other requests are being handled,
// possibly by this thread.
Debug.Assert(object.ReferenceEquals(HttpContext.Current.User, user));
それはDebug.Assert
成功することが保証されていますか?
Task.Delay
別のリクエストが保留中と同じスレッドによって処理された場合、そのリクエストは別HttpContext.Current.User
の を設定するので、継続が呼び出されたときに以前の状態が何らかの方法で保存および復元されますか?
私が想像できるのは、舞台裏で[ThreadStatic]
状態がスレッド自体のある種の辞書として保持され、スレッドがその辞書に戻った後にスレッドプールに戻ると、await
その辞書はどこかに安全に保管され、スレッドに戻されるということです。それは継続を実行します(または、スレッド上で、継続を処理するのが必ずしも同じスレッドであるかどうかはわかりません)。一部は私の想像にすぎないかもしれません。
それはある程度正確ですか?
更新:これを試みる小さなテストをまとめようとしました。これまでのところ、機能しているようで、何百ものリクエストのうち、アサーションが失敗したことはありません。テストが理にかなっていることを誰でも確認できますか?