WCF回调频道过早被处置?

时间:2009-05-14 22:20:25

标签: .net-3.5 wcf callback

我的应用程序正在使用带有回调通道的net.tcp WCF服务。出于某种原因,我无法在事件上发送回调。这就是我正在做的事情(所有代码服务器端):

初始化时:

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

活动:

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

此问题在SomeMethod()失败,但出现以下异常:{"Cannot access a disposed object.\r\nObject name: 'System.ServiceModel.Channels.ServiceChannel'."}

显然,即使客户端仍然能够使用直接(非回调)通道与服务器通信,某些东西也会处理回调通道。这很奇怪。我应该坚持哪个对象才能发出回调?是否必须运行某个线程?

5 个答案:

答案 0 :(得分:3)

Configure Tracing并查看您的频道出现了什么异常。

答案 1 :(得分:2)

我遇到了类似的问题,我的服务会对业务层进行异步调用,然后等待事件重新启动服务。当事件触发时,Callback上下文丢失。我没有详细研究为什么会这样,但我最终实现了一个解决方法,主要是存储对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);
}

注意:是的,我现在已经废除了从我的业务层火灾回到服务层的事件,但是因为我正在为业务层启动一个单独的线程,它仍然异步运行并且行为与我是一样直接以ASync方式调用BL并等待事件通知其完成。

PS:感谢Rory的想法和大部分代码来实现这一点。

答案 2 :(得分:0)

您是否尝试直接使用OperationContext.Current而不是实例变量Context?

答案 3 :(得分:0)

此问题已解决为我的错误。回调按设计工作,除了一些是陈旧的,当被调用时抛出异常。由于我没有尝试/捕捉它们,整个事件在那些陈旧的回调中打破:(。

感谢所有试图回答我问题的人。

答案 4 :(得分:0)

我的聊天应用中遇到了类似的问题。如果我关闭了我的应用程序,然后再次尝试打开,那么在打开频道时我会继续Cannot access a disposed object

通过应用程序向后追踪我执行了以下操作以找到根本原因。

  • 在我关闭之前对服务进行最终调用(注销)时,在客户端应用程序中设置一个断点。 - 这里没什么可报告的。
  • 远程在注销方法中调试服务器上的服务。 - 注意到回调不起作用并产生异常,因为频道因某种原因被处理掉了。
  • 检查了OperationContract的属性 - 发现问题!

问题是,如果我错了,WCF专家会纠正我,因为OperationContract就是这样

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

设置IsTerminating = true意味着在服务处理注销方法之前通道已关闭,因此当它尝试回调时,它无法进行回调。

设置IsTerminating = false并关闭客户端的频道为我排序问题。

在我的应用程序中,回调不应该发生,但这是一个单独的问题,而不是相关的。重点是,如果您对某个操作有IsTerminating = True,那么请确保您没有使用回调。