まどか の ブログ

~ はぐれSE 純情派 ~

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  124  : 記事  0  : コメント  408  : トラックバック  22

書庫

日記カテゴリ

わんくま同盟

WCFで双方向、つまりサービスからクライアントへのコールバックをおこなう際の注意点。

【WCF仕様】

PerSession, Duplex, NetTCPBinding, ConcurrencyMode=Single

【コード】

※コントラクトや構成ファイル、SVCUTIL.exeによる自動生成クライアントコード等は一切省略。

・Testメソッドを呼び出すとTestEventコールバックを発生させるというもの。

【サービス定義】

' User Service Callback
Public Interface ITestCallback

    Sub TestEvent()

End Interface

' User Service
Public Class TestService

    ' Service Method
    Pubic Sub SomeMethod()

    End Sub

    ' Service Method
    Pubic Sub Test()

        ' この実行コンテキストが完了したタイミングでコールバックをおこなう
        AddHandler OperationContext.Current.OperationCompleted, AddressOf TestCompleted

    End Sub

    ' Test Method Completed
    Pubic Sub TestCompleted(ByVal sender As Object, ByVale As EventArgs)

        Dim cb As ITestCallback = OperationContext.Current.GetCallbackChannel(Of ITestCallback)()

        cb.TestEvent()

    End Sub

End Class

【クライアント アプリケーション】

・サービスメソッドを連続で呼び出す。

Private Sub Button1_Click()

    _TestClient.Test()

    _TestClient.SomeMethod()  *1

End Sub

 

【現象】

タイムアウトにて例外発生。
現象的にはTest→SomeMethodの時点でSomeMethodの実行コンテキスト中にコールバックを送信しようとするため。
※予想。 というか例外トレースの最終メソッドがSomeMethodで例外後にコールバック受信プロシージャに遷移する。
この挙動はコントラクトのOneWayや同期/非同期呼び出しに関係なく発生する。
元々メッセージが完結(実行コンテキストの完了=呼び出し元のステップを抜ける)を待たずに
別のメッセージを発生させるとブロックされタイムアウトになることはMSDNで確認済み。

なお、*1 をなくすと例外なく動作する。

ちなみに実際の実装例としては、ログイン→ログイン通知受信→メンバ一覧取得のような場合がある。

【現状の回避策】

コールバックのコンテキスト(受信の実装)はクライアントに記述するが、
そのコントラクトのConcurrencyMode=Singleによりコールバック受信時の処理が同期になる。
現象で書いたように、Test→SomeMethodが動作するのはそれぞれがサービスへの要求つまり一方向であり
また連続するステートメント(同期)であるのでTestの実行コンテキストが完了してからSomeMethodを送信しているためである。
このことから、双方向のメッセージが(非同期のため?)重なってしまうことに原因がある。

そこでコールバック専用のサービスを用意する。つまりポートを2つ使うことになる。
さらにOperationCompletedイベントを
サービス側:サービス要求受信→コールバック送信、クライアント側:コールバック受信→サービス要求
の間で利用してメッセージを分断することにより上記動作を実現している。

 

#MSDNが未整備で例も少なく大変です。。。
#そんなわけで誰に確認したわけでもありません。あくまで私の調べた結果であります。
#したがって、突っ込みは大歓迎です。間違ってたらえらいことになりますので(自分が)

投稿日時 : 2007年10月30日 15:30

コメント

No comments posted yet.

Post Feedback

タイトル
名前
Url:
コメント