背景:WCF NetTCP with Background Threading
NetTCPバインディングを使用してWindowsサービス内でWCFサービスをホストするシステムがあります。コレクションに新しいサービスを追加するには、標準のWCF設定エントリを< system.serviceModel - > services />の中に追加して、サービスを初期化するために必要なホスティングフレームワークに指示するカスタム設定セクション内の行を追加します。各サービスは、独自のバックグラウンドスレッドとAppDomainインスタンスで初期化され、すべてを分離した状態に保ちます。ここで
はサービスが初期化されている方法の例です:
Host
- ServerManager
- ServiceManager
- BaseServerHost
ServerManagerのインスタンスは、標準のWCF実装嘘で、それぞれが単一のサービスインスタンスに相関ServiceManagersのコレクション(ServiceHost.Openを持っています/閉じるなど)。 ServiceManagerインスタンスは、BaseServerHost基本クラス(抽象的な)を使用して、サービスのインスタンスをインスタンス化します(設定に基づいて、標準アセンブリ/型定義を持ちます)。すべてのサービスは、それを使用できるようにするために、これを継承しなければなりません。 初期化プロセスの一環として、BaseServerHostは、いくつかのイベント、具体的には所有しているServiceManagerが接続するUnhandledExceptionイベントを公開します。
このプロセス全体は、WCFについて何も知らない人を連れて来ることができるため、私たちにとって非常にうまく機能します(1つのインスタンスは63のサービスを実行しています)。非常に迅速にサービスを作成できます。
質問:
私が遭遇した問題はバックグラウンドスレッディングです。エンドポイント上の公開されたメソッドの大部分は、他のシステムにメッセージを送信するなど、標準的な挿入/更新/削除メソッド呼び出し後にかなりの量のアクティビティを行います。パフォーマンスを維持するために(フロントエンドはWebベースです)、最初の挿入/更新/削除メソッドを実行させてから、バックグラウンドスレッドを起動して、エンドユーザーが待機する必要のないすべてのものを処理します完了する。このオプションは、そのバックグラウンドスレッドの何かが処理されなくなり、Windowsサービス全体がダウンするまでうまく動作します。これは設計上の理解ですが(と私はOKです)。
私の研究のすべてに基づいて、グローバルなtry/catch(バックグラウンドクラッシュの1.1処理を有効にするハッキングされた設定を使用しない)を実装する方法がないことがわかったので、私のチームは、適切な場所でそれを除いて、WCFのエンドポイント側で私が見つけたのは、各呼び出しで独自のスレッドにあるように見え、そのスレッドを「親」と話すことは悪夢でした。ここでは、サービスの観点からレイアウトです:
Endpoint (svc - inherits from BaseServerHost, mentioned above)
- Business Layer
- Data Layer
私はその後、BaseServerHostのUnhandledExceptionを発射しようとします(BaseServerHostから継承)エンドポイントインスタンスにビジネス層Iバブルでそれをバックグラウンドスレッドで例外をキャッチアップするときこの特定のサービス(それをインスタンス化した所有するServiceManagerによってアタッチされていた)のイベント。残念ながら、イベントハンドラは存在しないので、何もしません。私はこれを働かせるために数多くのことを試してきましたが、これまで私の努力はすべて無駄でした。
フルモデル(以下を参照)を見ると、ビジネス層に親エンドポイント(これは機能します)が分かるようにする必要があります。エンドポイントはServiceManagerについて知る必要がある実行中のBaseServerHostインスタンスこれをホスティングしているので、標準的なロギング手順で使用するために、これまでエラーをバブリングすることができます。
私はあまりにも運と静的クラスを試してみましたが、でも限りServerManagerのは、静的な作りとServiceManagersのその前に内部コレクションをexpotingとして行ってきました(そう、彼らがシャットダウンすることができます)が、そのコレクションは常に空またはnullできたHost
- ServerManager
- ServiceManager <=====================
- BaseServerHost ||
- Endpoint (svc) ||
- Business Layer <======
- Data Layer
。
この作品を作る上での考え方は?
編集:もう少し掘り下げた後、私はこの作業をどのように想像しているかの例を見つけました。標準のASP.NET Webサイトでは、任意のページ/ハンドラなどでHttpContext.Currentプロパティを使用して、そのリクエストの現在のコンテキストにアクセスできます。これは、「ServiceManager.Current」がそのサービスの所有するServiceManagerを返すようにするためには、これをどのように動作させたいのです。多分それが助けになるでしょうか?
これは間違いなく高レベルから有望であり、私はそれが動作しない原因となっている実装方法だと思っています。サービス(BaseServerHost)が初期化された直後に、私はこれを行います: CallContext.SetData( "ApplicationName"、ApplicationName); CallContext.SetData(ApplicationName + "ServiceManager"、this); すぐに直接ウィンドウを使用すると、ServiceManagerインスタンスが表示されます。私は例外をキャッチすると、CallContext.GetData( "ApplicationName")はnullです。 私は間違って何かをしなければならないので、うまくいけば、あなたはこれを行うためのいくつかのリンクを見つけることができます。 – RubyHaus
@digitall - 私はいくつかの情報といくつかのリンクを追加しました。私が考えていたアイディアが、あなたのシステムの仕組みに必ず当てはまるということは私には分かりません。私の答えには、あなたが話していることが当てはまるかどうかを知ることができるという十分な情報があります。 – wageoghe
私はこれを忘れていません - 私は出張に呼ばれて、もう一週間ほど見直されません。私はその時さらに少し掘り下げていくつもりです。 – RubyHaus