2009-05-14 21 views
0

私のアプリケーションは、コールバックチャネルでnet.tcp WCFサービスを使用しています。何らかの理由で私はイベントでコールバックを送信できません。初期設定ではWCFコールバックチャネルは時期尚早に処理されますか?

:イベントで

OperationContext Context { get; protected set; } 
... 
Context = OperationContext.Current; 

:ここで私は(すべてのコード・サーバー・サイド)をやっているのです{"Cannot access a disposed object.\r\nObject name: 'System.ServiceModel.Channels.ServiceChannel'."}

var callback = Context.GetCallbackChannel<IServiceCallbackContract>(); 
callback.SomeMethod(); 

これは、次の例外を除いてSomeMethod()に失敗します

明らかに、クライアントが直接(非コールバック)チャネルを使用してサーバーと通信できる場合でも、何かがコールバックチャネルを破棄します。これはかなり奇妙です。コールバックを発行するためにどのオブジェクトを保持する必要がありますか?これは実行しなければならないスレッドがありますか?

+0

コールバックを行うとサービスがまだ開いていますか? – Gromer

答えて

0

問題は私のエラーとして解決されました。コールバックは設計通りに機能しましたが、一部のものは古くなっていましたが、呼び出されると例外がスローされました。私は、全体のイベントがこれらの古いコールバックで破った:(それらを引く/しようとしていなかったので。私の質問に答えることを試みたすべての人に

感謝。

3

Configure Tracingあなたのチャンネルに違反している例外を確認してください。

+0

良いアイデア...表示されているものを見せてください – galets

2

私のサービスでビジネスレイヤーへの非同期呼び出しが行われ、イベントがサービスに戻るのを待つ同様の問題が発生しました。イベントが発生するたびに、コールバックコンテキストが失われました。私はこれがなぜであるかの詳細を掘り下げませんでしたが、本質的にcurrentcontextへの参照を格納し、別のThreadを呼び出してビジネスレイヤを呼び出すという回避策を実装してしまいました。私は参照を保存しています。

1)自分の入力要求とコールバックへの参照の両方を含む新しいクラスを作成します。

public struct MyCallbackDetails { 
    public MyCallbackDetails(IMyServiceCallback callback, RequestType request) : this() 
     Callback = callback; 
     Request = request; 
} 

public IMyServiceCallback Callback { get; set; } 

public RequestType request { get; set; } 
} 

2)その後、私はMyCallbackDetailsを渡して別々のスレッドをオフに解雇だろうではなく、単に要求の対象:

public ResponseType MyServiceMethod(RequestType request) { 
    //...Do Some Stuff 
    //Create MyCallbackDetails object to store reference to the callback and keep channel open 
    MyCallDetails callDetails = new MyCallDetails(OperationContext.Current.GetCallbackChannel<IMyServiceCallback>(), request); 
    //Fire off a new thread to call the BL and do some work 
    Thread processThread = new Thread(RunCallbackMethod); 
    processThread.Start(callDetails); 
} 

3)そして、私のRunCallbackMethodがBLの呼び出しを行うと、コールバックで応答します。

void RunCallBackMethod(Object requestDetails) 
{ 
    //Use callbackdetails to make BL calls 
    MyCallbackDetails callDetails = (MyCallbackDetails)requestDetails; 
    // Make BL call - all code under here is syncrhonous 
    ResponseType response = BusinessLayer.BusinessMethod(callDetails.Request); 
    //NB: If your responsetype is a business object you will need to convert it to a service object 
    callDetails.Callback.SomeMethod(results); 
} 

NB:はい、私はすぐに戻ってサービス層への私のビジネスレイヤ火災からのイベントを持って離れて行っているしかし、私は、ビジネスレイヤのための別々のスレッドをオフに発射していて、それはまだ非同期に実行され、同じ動作をしますあたかも私がBLをASyncの方法で直接呼び出していて、イベントが完了したことを通知するのを待っているかのように。

PS:これを実装するためのアイデアとコードのほとんどはRoryです。

0

インスタンス変数Contextの代わりにOperationContext.Currentを直接使用しようとしましたか?

+0

他のスレッドでコールバックが実行されているので確かにnullです – galets

0

私は私のチャットアプリで同様の問題があった。場合私は自分のアプリを閉じて、再び開いてみた。私はチャンネルを開くときにCannot access a disposed objectを得続けた。

アプリを逆にたどって、根本原因を突き止めるために次のことを行いました。

  • サービスを最後に呼び出すとき(ログオフ)に閉じるときに、クライアントアプリケーションにブレークポイントを設定してください。 - ここに報告するものはありません。
  • リモートログオフ方式でサーバー上のサービスをデバッグしました。 - チャネルが何らかの理由で破棄されたため、コールバックが機能せず、例外が生成されたことに気付きました。
  • OperationContractの属性を確認しました - 問題が見つかりました!

問題があって、私が間違っている場合はWCFの専門家は、OperationContractがそう

[OperationContract(IsInitiating = false, IsTerminating = true)] 
bool RemoveUser(Client user); 

ようIsTerminating = trueを設定したことが、私を修正しないサービスは、ログオフの方法を処理していた前に、チャネルが閉じられたことを意味しそれがコールバックしようとしたとき、それはできませんでした。

設定IsTerminating = falseクライアント側のチャンネルを閉じて問題を分類しました。

私のアプリでは、コールバックは起こっていないはずですが、別の問題がすべて一緒になっていて関連していません。要点は、操作中にIsTerminating = Trueがある場合、コールバックを使用していないことを確認することです。

関連する問題