17

WCF サービスのコードをレビューしています。各メッセージのヘッダーに、サービスが後で DB への接続文字列を構築するために使用するデータを挿入します。これは、サービスが多数の異なるサイトで使用され、それぞれがサービスが照会する必要がある独自の DB を持っているためです。wcf 拡張性を使用します。リクエストを受信した後、メッセージ ヘッダーからデータを抽出し、(IExtension を実装する) コンテキストを作成し、それを OperationContext.Current.Extensions に追加するカスタム MessageInspector があります。返信を送信する前に、カスタム コンテキストが Extensions コレクションから削除されます。

ここで説明するように、これはかなり一般的なパターンです。

現在の WCF 呼び出しのデータをどこに保存しますか? ThreadStatic は安全ですか?

そしてここ:

http://social.msdn.microsoft.com/Forums/vstudio/en-US/319cac66-66e8-4dfe-9a82-dfd289c9df1f/wcf-doesnt-have-session-storage-so-where-should-one-store- call-specific-data?forum=wcf

サービスがリクエストを受け取り、それを処理し、返信を送信し、次のリクエストを受信する限り、これはすべて正常に機能します。しかし、サービスがリクエストを受信し、応答する前に 2 番目のリクエストを受信した場合はどうなるでしょうか? テスト用に小さなコンソール アプリケーションを作成しました。2 つの異なるスレッドから 2 つのメッセージを送信します。最初のリクエストが完了する前に 2 番目のリクエストが確実に届くように、wcf サービスを 2 秒間待機させました。

サイト ID : test1450 ; セッション: uuid:2caf47cf-7d46-4d72-9275-d9c037fa0e70;id=2: スレッド ID: 6

サイト ID : test1450 ; セッション: uuid:2caf47cf-7d46-4d72-9275-d9c037fa0e70;id=3: スレッド ID: 22

wcf は 2 つの異なるスレッドで実行される 2 つのセッションを作成するように見えますが、サイト ID は同じです。すべきではありません。このことから判断すると、OperationContext.Current.Extensions はスレッド間で共有されるコレクションのように見えます。今、私は自分のテストが間違っていて、何かを見逃していると思いがちです。

同様のことを試した人はいますか? OperationContext.Current がスレッドセーフではないことがわかりましたか?

4

1 に答える 1

12

OperationContext.Current は、HttpContext.Current などの他の同様のプロパティと同様に、スレッド アフィン (またはスレッド静的) 値を持ちます。したがって、複数のスレッドがそれらを読み取ることができるという意味でスレッドセーフですが、異なるスレッドは異なるインスタンスを取得します。これらは、特定のスレッドとインスタンスの間の辞書と考えることができます。

したがって、このコンテキストではスレッドセーフではありません。

リクエストはスレッド プールによって処理されるため、同時リクエストには異なるスレッド ID が割り当てられます。(スレッドプールがいっぱいになるまで、リクエストは保留されます)

于 2013-10-10T09:42:13.507 に答える