AspNetSynchronizationContext
-
11-12-2019 - |
質問
新しいC#5非同期モデルを使用しようとすると、それは私にとって驚くべきことでした AspNetSynchronizationContext
は内部クラスである(と同様に AspNetSynchronizationContextBase
ベース)。したがって、文書化されていません。しかし、あなたの中でasync/await機能を利用するときにそれが何をするかを知ることが不可欠ですASP.NET コードだ私はそれを正しいですか
それは... します。 あなたの継続が同じを得ることを保証して下さい HttpContext.Current
元の発信者として?それは... しません 継続が呼び出し元と同じスレッドで実行されることを保証しますか?
後者の仮定が真実ではなく、元のスレッドを取得した場合、継続で同じスレッドコンテキストを確実に取得できますか?私はスレッドとスレッドローカルストレージに関連付けられたプリンシパル/カルチャを意味しますか?それは重要な理由ですASP.NET ローカリゼーションはスレッドのカルチャに依存し、私のアプリケーションは.NETロールセキュリティモデル(スレッドのプリンシパル)に依存しています。
解決
あなたの継続が同じHttpContextを取得することを保証するのは正しいですか?元の発信者として現在?呼び出し元と同じスレッドで継続が実行されることを保証するものではありませんか?
はい。, HttpContext.Current
は保持され、はい、継続は別のスレッドで実行される可能性があります。
私はスレッドとスレッドローカルストレージに関連付けられたプリンシパル/カルチャを意味しますか?それは重要な理由ですASP.NET ローカリゼーションはスレッドのカルチャに依存し、私のアプリケーションは.NETロールセキュリティモデル(スレッドのプリンシパル)に依存しています。
通常のスレッドローカルストレージは失われます。これを軽減するには、以下を使用します LogicalCallContext
(と流れる ExecutionContext
)、しかし、 async
変数を直接参照する方が簡単です。
プリンシパルは常に保持されます;そうでなければ、セキュリティ上のリスクになります。これは次のように流れます ExecutionContext
.
私は文化が流れると信じています AspNetSynchronizationContext
, 、しかし、私はこれをテストしていない .NET4.5の新しい実装.
あなたは私を見つけることができます 上のMSDNの記事 SynchronizationContext
助けてくれました。これは公式のドキュメントではありません(私はMicrosoftでは機能しません)が、少なくともそれは何かです。に注意してください。 AspNetSynchronizationContext
その記事で参照されているのは、現在呼ばれています LegacyAspNetSynchronizationContext
.NET4.5では。
もう1つの優れたリソースは、Stephen Toubのものです。 ExecutionContext
対... SynchronizationContext
.
他のヒント
elepenceContextをキャプチャしながら、同じSynchronizationContextの実行をキャプチャして実行することは、AWAITERによって異なります。
最も一般的なAWAITER(「何か」を「待っているときに呼び出されたgetawaiter()メソッドから返されたタイプ」は、task.getAwaiter()によって返されるTaskAwaiterです。デフォルトでは、TaskAwaiter は現在のSynchronizationContextをキャプチャし、キャプチャされたSynchronizationContext で継続デリゲートを実行します。これは、あなたがあなたのメソッドの残りの部分でhttpcontext.currentを使うことができるでしょう、そしてそれが継続として実行されることを気にしないでください。そのため、このコードは予想通りに機能します(「B」を「B」を書き込む部分は、最初の行として同じSynchronizationContext):
.
HttpContext.Current.Response.Write("A");
await Task.Delay(1000);
HttpContext.Current.Response.Write("B")
Task.ConfigureAwait(false)
メソッドを使用してこの動作を変更できます。
もちろん、Task.runまたはtask.factory.startnewを呼び出すと、SynchronizationContextを再度キャプチャする責任があります。
頑張ってください。