永远不会调用WCF回调实现函数

时间:2012-03-29 09:01:06

标签: wcf callback

我正在设计一个带回调的WCF服务,但我的回调函数的实现永远不会被调用。我对生成的服务代理感到困惑,所以请帮忙。

以下是场景:在服务器端,我定义了服务接口IMyService和回调接口IMyServiceCallback,我还在服务器项目中实现了IMyService。除了服务器项目,我肯定有另一个客户端项目,我在VS中添加了服务引用。我在客户端实现了IMyServiceCallback接口。所以这就出现了问题:当我调试它时,函数永远不会进入我的IMyServiceCallback实现,当然所需的结果永远不会出现。

这就是我困惑的地方:当我在客户端添加服务引用时,它实际上在本地生成了三个接口:IMyService,IMyServiceCallback和IMyServiceChannel以及客户端代理类。在我的本地IMyServiceCallback实现中,我声明该类实现了本地IMyServiceCallback接口,而不是服务端的接口。这可能是问题吗?为什么在不同项目下有两个接口声明(因此不同的命名空间)?我实现客户端接口的原因是,如果我从服务器端接口实现,它会给出错误:“当我尝试调用服务时,提供给ChannelFactory的InstanceContext包含一个不实现CallbackContractType错误的UserObject”。另一个令人困惑的部分是,在服务器端,如果我将回调接口名称声明为IMyCallback,或者其他任何东西,而不是IMyServiceCallback,客户端上生成的接口仍然是IMyServiceCallback,这是服务接口的名称加上后缀“回调”。在这种情况下,我还得到“提供给ChannelFactory的InstanceContext包含一个不实现CallbackContractType错误的UserObject”。

我想有些东西我误解了“添加服务引用”以及我应该如何实现接口(实现哪一个)。谁能帮助我?谢谢!

更新:

我以某种方式解决了这个问题。首先,两个声明是好的。本地客户端需要实现添加服务引用时生成的本地接口。我的问题是我还定义了一个DataContract,但生成的参考文件没有它。它可能是因为我已经添加了服务项目的程序集作为参考(有人说在这种情况下添加服务引用不会生成Datacontract)或因为我缺少DataMember属性。但无论如何,在我修复了两个部分后,该功能现在正在运行。

3 个答案:

答案 0 :(得分:2)

当您“添加服务引用”并生成代理时,它与您的服务实现完全分开。请记住,您可能正在使用尚未编写且无法访问服务源代码的服务。

客户端代码应使用客户端生成的接口。如果您更改了服务,则需要重新生成代理。

如果您发现这太混乱,并且您知道您将始终控制两端,则可以在公共程序集中共享服务接口,并使用DuplexChannelFactory.CreateChannel()在运行时生成代理类。

至于你的问题,我只能假设你没有正确注册你的回调。这包括here

答案 1 :(得分:0)

如果要发布,则必须在同一项目中一起实现IMyServiceCallback和IMyService。  如果只订阅,则必须实现IMyServiceCallback接口

答案 2 :(得分:0)

当我的回调指令嵌入到函数调用中时,我解决了这个问题。 我了解到将回调放在一个不返回结果的方法中工作正常。 但是,当回调指令放在函数中时,我遇到了超时问题。

我通过在被调用函数中使用backgroundworker线程来解决它:

public static IMyServiceCallback Callback;
.
.
.

        TaskStateData taskStateData = GetSomeData();

        BackgroundWorker backgroundWorker = new BackgroundWorker();

        backgroundWorker.DoWork += (se, ev) =>
            {
                Tuple<OperationContext, TaskStateData> data = ev.Argument as Tuple<OperationContext, TaskStateData>;
                var operationContext = data.Item1;

                if (operationContext != null)
                {
                    Callback = operationContext.GetCallbackChannel<IMyServiceCallback>();
                    Callback.OnCallBack();
                }
            };

        Tuple<OperationContext, TaskStateData> payload = new Tuple<OperationContext, TaskStateData>(OperationContext.Current, taskStateData);
        backgroundWorker.RunWorkerAsync(payload);