あなたはすでに答えを知っているように思えます:ロングポーリングを使用してください。:) したがって、説明しなければならない唯一のことは、WCF を使用して可能な限り最も効率的な方法でこれを達成する方法です。
基礎:
- 最初に、各「長いポーリング」の長さを決定します。議論のために、5 分のタイムアウトを選択します。
- クライアント側バインディングで、
sendTimeout="00:05:00"
.
- ロング ポーリングに XmlHttpRequest (XHR) を使用するのと同様に、実際にタイムアウトが発生した場合は、それを検出して次のポーリング リクエストを再発行する必要があります。これは、WCF では非常に簡単です。なぜなら、特定の例外 があるため
TimeoutException
です。これをキャッチして、これが問題であり、他の例外であったことを簡単に検出できます。
- WCF サービスをホストしている方法によっては、最大 5 分間の処理を許可するように構成する必要があります。純粋な WCF の観点からは、必ず
receiveTimeout="00:05:00"
. ただし、ASP.NET 内でホストしている場合は、ASP.NET ランタイムのタイムアウトを長く設定する必要があります<httpRuntime executionTimeout="300" />
(注:この属性の測定値は秒単位です)。
クライアントで効率的であること
サービスを同期的に呼び出すようにクライアントをセットアップし、クライアントが応答を待っている間に 5 分間ブロックする場合、それはシステム リソースの効率的な使用とは言えません。これらの呼び出しをバックグラウンド スレッドに配置することもできますが、呼び出しが未処理である間、スレッド リソースを食いつぶすことになります。これに対処する最も効率的な方法は、非同期操作を使用することです。
サービス コントラクトを手動で作成している場合は、MSDN のこのセクションでOperationContractAttribute.AsyncPattern
BeginXXX
、各呼び出しに/ EndXXX
async メソッド ペアを追加する方法の詳細を確認することをお勧めします。ただし、svcutil
操作コントラクトを生成するために を使用している場合、非同期メソッドを生成するために必要なことは/async
、コマンド ラインでオプションを渡すことだけです。このトピックの詳細については、MSDN の同期と非同期のトピックを参照してください。
非同期操作の定義が完了したので、パターンは XHR での作業に非常によく似ています。デリゲートBeginXXX
を渡すメソッドを呼び出しAsyncCallback
ます。このBeginXXX
メソッドは を返しますIAsyncResult
。これは、操作を待機できるようにしたい場合 (より高度なシナリオでは) 保持するか、無視することができます。その後、WCF インフラストラクチャは要求を非同期的にサーバーに送信し、裏での反応。応答が受信されるか、例外が発生すると、BeginXXX
メソッドに渡したコールバックが呼び出されます。EndXXX
このコールバック メソッド内で、渡された を渡す対応するメソッドを呼び出す必要がありIAsyncResult
ます。への通話中にEndXXX
メソッドの呼び出し中に発生した可能性のあるあらゆる種類の論理エラーに対処するために例外処理を採用する必要がありますが、これは、TimeoutException
先ほど説明したエラーをキャッチできる場所でもあります。適切な応答が得られたと仮定すると、データはEndXXX
呼び出しから返され、意味のある方法でそのデータに反応できます。
注:このパターンについて覚えておくべきことの 1 つは、スレッドの性質です。WCF からの非同期コールバックは、マネージド スレッド プールのスレッドで受信されます。Invoke
WPF や WinForms などのテクノロジで UI を更新することを計画している場合は、またはBeginInvoke
メソッドを使用して UI スレッドへの呼び出しをマーシャリングする必要があります。
サーバー上で効率的であること
クライアントの効率を心配するつもりなら、サーバーに関しては二重に心配する必要があります。明らかに、このタイプのアプローチでは、クライアントに通知を送り返す理由が生じるまで、接続を開いたままにして保留にする必要があるため、サーバー側により多くの要求が課せられます。ここでの課題は、WCF ランタイムを、実際にイベントが送信されているクライアントの処理だけに結び付けたいということです。他のすべては、イベントが発生するのを待って、スリープ状態にする必要があります。幸いなことに、クライアント側で使用したのと同じ非同期パターンがサーバー側でも機能します。ただし、大きな違いがありますIAsyncResult
。メソッドから(したがって、WaitHandle
) を返す必要がBeginXXX
あり、WCF ランタイムは、メソッドを呼び出す前にシグナルが送信されるのを待機します。EndXXX
方法。
以前に提供したリンク以外の MSDN 内のドキュメントの方法はあまり見つかりません。残念ながら、非同期サービスの作成に関するサンプルはあまり役に立ちません。とは言うものの、ウェンロン ドンは、非同期モデルを使用した WCF サービスのスケーリングに関する記事を書いています。
これを超えて、正直なところ、サーバー側で非同期モデルを実装する最善の方法についてあまりアドバイスすることはできません。なぜなら、そもそもイベントがどのような種類のデータ ソースから来るのかに完全に依存するからです。ファイル I/O? メッセージキュー? データベース?ファサードを提供しようとしている、独自のメッセージング サービスを備えた他のプロプライエタリ ソフトウェアはありますか? わかりませんが、それらはすべて独自の非同期モデルを提供する必要があり、独自のサービスをピギーバックして可能な限り効率的にすることができます。
処方箋の更新
これはよくある回答のように思われるので、ここに戻って状況の最近の変化を踏まえて最新情報を提供する必要があると考えました。この時点で、この正確な機能を提供するSignalRと呼ばれる .NET ライブラリがあり、サーバーとのそのような通信を実装することをお勧めします。