我正在设计一个带有回调的WCF服务,但我的回调函数的实现从未被调用过。我对生成的服务代理感到困惑,所以请帮助我。
场景如下:在服务器端,我定义了服务接口IMyService和回调接口IMyServiceCallback,我还在服务器项目中实现了IMyService。除了服务器项目,我肯定还有另一个客户端项目,我在其中添加了VS中的服务引用。我在客户端实现了IMyServiceCallback接口。所以问题来了:当我调试它的时候,这个函数从来没有进入我的IMyServiceCallback实现,当然也没有得到想要的结果。
这就是我感到困惑的地方:当我在客户端添加服务引用时,它实际上在本地生成了三个接口: IMyService、IMyServiceCallback和IMyServiceChannel以及客户端代理类。在我的本地IMyServiceCallback实现中,我声明该类实现本地IMyServiceCallback接口,而不是来自服务端的接口。这会是问题所在吗?为什么在不同的项目下有两个接口声明(因此有不同的命名空间)?我实现客户端接口的原因是,如果我从服务器端接口实现,当我试图调用服务时,它会给出错误:“提供给ChannelFactory的InstanceContext包含不实现CallbackContractType的UserObject错误”。另一个令人困惑的部分是,在服务器端,如果我将回调接口名称声明为IMyCallback或其他名称,而不是IMyServiceCallback,则在客户端生成的接口仍然是IMyServiceCallback,这是服务接口的名称加上后缀" callback“。在这种情况下,我还得到了“提供给ChannelFactory的InstanceContext包含没有实现CallbackContractType错误的UserObject”。
我想我对“添加服务引用”以及我应该如何实现接口(应该实现哪个接口)有一些误解。有人能帮帮我吗?谢谢!
更新:
我以某种方式解决了这个问题。首先,这两个声明是可取的。本地客户端需要实现本地接口,该接口是在添加服务引用时生成的。我的问题是我也定义了一个DataContract,但是生成的引用文件没有它。这可能是因为我添加了服务项目的程序集作为引用(在本例中有人说添加服务引用不会生成Datacontract),也可能是因为我缺少DataMember属性。但不管怎样,在我修复了这两个部分之后,函数现在可以工作了。
发布于 2012-03-29 10:17:10
当您“添加服务引用”并生成代理时,它与您的服务实现是完全分开的。请记住,您可能正在使用尚未编写的服务,并且无法访问服务源代码。
客户端代码应该使用客户端生成的接口。如果您更改了服务,则需要重新生成代理。
如果您觉得这太混乱了,并且您知道您将始终控制两端,那么您可以共享公共程序集中的服务接口,并在运行时使用DuplexChannelFactory.CreateChannel()
生成一个代理类。
至于你的问题,我只能假设你没有正确注册你的回调。这篇文章涵盖了here。
发布于 2012-03-29 09:30:01
如果你想发布,你必须在同一个项目中同时实现IMyServiceCallback和IMyService。如果只订阅,则必须实现IMyServiceCallback接口
发布于 2013-01-30 01:14:54
我修复了回调指令嵌入到函数调用中时的问题。我了解到,将回调放在不返回结果的方法中可以很好地工作。然而,当回调指令被放在函数中时,我遇到了超时问题。
我通过在被调用的函数中使用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);
https://stackoverflow.com/questions/9922174
复制相似问题