5

次のシナリオを検討してください。

  1. 非同期 .ashx ハンドラー
  2. 非同期 .asmx Web サービス メソッド
  3. 同期 MVC 5 コントローラー アクション メソッド

「論理」httpリクエスト中に一貫してアクセスできる「論理スレッド」固有のデータを設定する方法を見つけようとしています。つまり、非同期ハンドラーの「BeginExecute」部分のスレッドでデータが設定された場合ASP.NET が別の OS/.Net スレッドで「EndExecute」部分を実行したとしても、データはその asnc ハンドラの「EndExecute」部分で利用できると考えるでしょう。

さらに、2番目のリクエストが最初のhttpリクエストに以前に割り当てられたスレッドに割り当てられた場合、それがあったOS / .Netスレッドの「BeginExecute」部分のデータセットは、後続のhttpリクエストでは利用できないと予想しています。 「BeginExecute」部分にありましたが、最初の http 要求が非同期操作に入ったときにこのスレッドが解放されました (そして、まだ非同期操作を完了している可能性があります)。

.Netの「論理スレッド」または「論理スレッドコンテキスト」という言葉は、実際には、私が言及したのと同じ「論理」操作フローを意味すると思います(再割り当てされ続ける基礎となるOS / .Netスレッドではありません)。ワークフローの観点から見ると、各 http リクエストは新しい「論理」操作です (複数のユーザーが同じ Web サービスを順次または並行して呼び出したとしても、各リクエストは新しい個別の論理操作です)。つまり、「論理」操作は 1 回限りであり、繰り返すことはできません。ただし、同じ基礎となる OS/.Net スレッドは、可用性に基づいて到着したときに「論理」操作にマップできます。

さらに、このデータを HttpContext.Current の種類の静的プロパティとして公開したいと考えています。これは驚く人もいるかもしれませんが、非同期の .asmx Web サービス メソッドなどを使用している場合、HttpContext.Current は正しく機能しません。HttpContext.Current は常に正しい HttpContext を返す必要があるという Web 上のコンテンツを読んだことがあると確信していますが、.asmx Web メソッドの EndExecuteMethod では null として表示されています。私の最後の発言が正しいかどうかを誰かが確認できれば素晴らしいことですが、この発言は私がここで尋ねようとしている全体的な質問ではありません.

かなりの量の文献を読んだ後 (例: log4net.ThreadContext と log4net.LogicalThreadContext の違いは何ですか?http://msmvps.com/blogs/jon_skeet/archive/2010/11/08/the-importance-of-context -and-a-question-of-explicitness.aspxhttp://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.htmlなど、MSDN ドキュメントを含む)、ここに私の推論があります:

  1. ThreadStatic は、「論理」操作ではなく、基礎となる OS/.Net スレッドに対してローカルであるため、私の例では; 2 番目の http 要求が最初のスレッドの「BeginExecute」と同じスレッドに割り当てられた場合、「BeginExecute」の最初の http 要求で設定されたデータは、次の http 要求で表示されます。そして、このデータは、たまたま .Net によって別のスレッドに再割り当てされた場合 (ほとんどの場合に発生します)、"EndExecute" で使用できません。
  2. Thread.SetData は、私のユースケースではさらに問題があります。データ スロットを渡す必要があります。Thread.GetNamedDataSlot の戻り値からデータ スロットを渡す場合、アプリ ドメイン全体で情報を利用できます。名前付きデータスロットはスレッド間で共有されるため。
  3. CallContext.SetData は ThreadStatic に似ています (つまり、アプリ ドメインによって共有されませんが、異なる http 要求が同じ基になる OS/.Net スレッドに割り当てられると、同じデータが表示されます)。CallContext.SetData は、RPC 呼び出しのコンテキスト データをマーシャリングする追加機能を提供します。これは、現在尋ねられている質問には関係ありません。
  4. 次に、ThreadLocal クラス (.Net 4/.Net 4.5) があります。私の問題の一部を解決できたようです.BeingExecute操作のstateObject内にそれを渡し、endExecute操作の同じstateObjectパラメータから抽出できました。この観点から、ThreadLocal は .Net の非同期サポート用に作成されているようです。ただし、HttpContext.Current のようにアクセスする必要がある場合は機能しません。その「論理スレッドの静的」インスタンスを保持する方法がないためです (前の 3 つのポイントで何か間違ったことを言っていない限り)。
  5. そして最後に、CallContext.LogicalSetData が私が達成しようとしていることを実行しているようです。CallContext.LogicalSetData および CallContext.LogicalGetData メソッドのセットを使用して、「論理タスクの実行」に対して正しく機能する HttpContext.Current のような影響を達成できるはずです。

では、次の質問に移ります。

  1. 私が上で言ったことはすべて正しいですか。私が行ったすべての誤った主張を修正してください。
  2. 私が見逃した.Netのスレッドの静的な種類の機能に利用できる他のオプションはありますか?
  3. CallContext.LogicalSetData/LogicalGetData はコンテキスト データを RPC 呼び出しに渡しますか (msdn ページでは明確に言及されていません。http: //msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.callcontext.logicalsetdata (v=vs.110).aspx )。
  4. CallContext.LogicalSetData/LogicalGetData を使用することの欠点 (パフォーマンス上またはそれ以外) はありますか。
  5. このページでは、LogicalSetData のコピー オン ライト動作について説明しています: http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html。非同期ハンドラー/非同期 MVC 5 アクション メソッドのコンテキストでは、logicalsetdata を使用して参照型を保存し、後で参照型の状態を変更すると、どのような影響がありますか。再帰とは何ですか。
  6. Mutation/logicalsetdata/async については、オブジェクトを変更しても何が問題なのかまだわかりません。非同期メソッドが開始されると、copy-on-write 動作により、次に logicalsetdata が呼び出されたときにコンテキスト データのコピーがトリガーされます。これは浅いコピーであるため、参照オブジェクトは実際には 2 つの論理コンテキストで共有され、一方のコンテキストでの変更はもう一方のコンテキストで表示されます。これは通常、参照型に期待されることです。

多くの参考文献を含む長い質問ですが、うまくいけば、私は自分の研究をうまく行い、その答えが他の人にも役立つことを願っています.

4

1 に答える 1

0

「論理」httpリクエスト中に一貫してアクセスできる「論理スレッド」固有のデータを設定する方法を見つけようとしています

唯一の可能なオプションはHttpContext.Current.Items、および論理CallContextです。

さらに、OS/.Net スレッドの「BeginExecute」部分のデータ セットは、後続の http 要求では利用できないと予想しています。

HttpContext.Current.Items新しいリクエストでは常にクリアされますが、論理CallContextデータを自分でクリアする必要があります。

たとえば、async .asmx Web サービス メソッドを使用している場合、HttpContext.Current は正しく機能しません。

これは驚くべきことです。試したことはありませんが、動作するはずです。.NET 4.5をターゲットにして .NET 4.5 を実行していて (つまりtargetFramework、.4.5web.configasync void

[ThreadStatic]、スレッド ローカル データ スロット、(non-logical) CallContext、およびThreadLocalはすべてスレッド固有のデータであり、非同期コードでは機能しません。

私が上で言ったことはすべて正しいですか。私が行ったすべての誤った主張を修正してください。

質問のテキストが多すぎます。Stack Overflow はメンタリング サイトではなく、Q&A サイトです。

私が見逃した.Netのスレッドの静的な種類の機能に利用できる他のオプションはありますか?

いいえ。

CallContext.LogicalSetData/LogicalGetData はコンテキスト データを RPC 呼び出しに渡しますか

何も思いつきません。試してみてください。

CallContext.LogicalSetData/LogicalGetData を使用することのマイナス面 (パフォーマンス上またはそれ以外) はありますか。

明確なパフォーマンス ヒットがあります。.NET フレームワークは、一般的なケース (論理呼び出しコンテキスト データなし) に対して高度に最適化されています。

logicalsetdata を使用して参照型を保存し、後で参照型の状態を変更すると、どのような影響がありますか。

論理CallContextには浅いコピーオンライト動作があります。したがって、あらゆる種類の非同期フォーク/ジョイン同時実行 (つまり、Task.WhenAll) は、その状態を共有することになります。を使用するConfigureAwait(false)と、競合状態になる可能性もあります。

HttpContext.Current問題を実際に解決するには、最初にが期待どおりに機能しない理由を調べることをお勧めします。私の推測では(プロジェクトを見ずに) 、代わりににtargetFramework設定されています。動作させることができれば、最もパフォーマンスの高い選択肢です。4.04.5HttpContext.Current.Items

于 2014-05-26T03:08:12.767 に答える