以前書いた.NET Remotingでの双方向通信 、サーバ側からクライアントにイベントを飛ばすという形で逆方向通信を行うものでした。
そこではクライアント側にあるイベントハンドラには[Oneway]修飾子を付けるように書いたのですが、実は意味が分かっていませんでした。文字通り一方通行であるということを指示するものでして、呼び出し側には返値・例外が返ってきません。まぁイベントですから返り値を求めることも少ないでしょうし、多くの場合では付けて問題ないかと。
余談。返り値のあるイベントハンドラを作ると最後に実行された(最後に追加された?)イベントハンドラの返り値がイベント発信側に渡るようです。 [参考] C# - 複数のイベントハンドラをセットしたメソッドを呼び出したときの戻り値 (おのでら氏)
ただ副作用あり。イベントハンドラが呼び出される前にサーバ側は次の処理にかかるようです。イベントが受け取られなくてもエラーを出しても知らん振りなのですから、次の処理にすぐさまかかった方がサーバ側のパフォーマンスは上がる。実際のイベントを.NET Remoting越しに処理するのは別のスレッド、おそらくスレッドプールに任されるのでしょう。
ここで短時間にたくさんのイベントを発信すると、イベントハンドラが呼び出される順番が変わることがありえると分かったのが昨日。スレッドプールのキューには順番通りに入っているのでしょうが、実行中に追い越しが発生すると思ってます。
[Oneway]と外すと全てのイベントハンドラが処理を終えるまで次の処理に進まないため、イベント発信を単一スレッドにやらせている限りは順番が入れ替わるということは防げます(受信終わるまで次のイベントが発信できない)。
ただしサーバ側パフォーマンスは落ちるでしょうし、クライアント側が死んでしまった場合サーバは延々と返り値を待つことになりますので、
- クライアント側は受信したらすぐに処理を返して、実際の処理はバックグラウンドで行う
- サーバ側はイベント発信処理をタイムアウト付き非同期処理する
などの対策が要るでしょう。[Oneway]付けとけばやってくれる非同期処理を自分でやることになる…
Comments