最近项目上做东西需要用到进度条,进度是调用WCF,想要通过回调显示进度,于是研究了一下WCF服务端如何调用客户端进行双向通信,发现需要用到CallbackContract,由客户端实现,然后客户端暴露出一个回调的EndPoint给服务端,服务端从调用的Context中拿到回调地址,然后通过CallbackContract进行回调。
Contract定义包含两部分,正常的服务Add方法,和一个回调更新进度的Percent方法:
//在ServiceContractAttribute上指定回调的契约类型 [ServiceContract(CallbackContract = typeof(ICallback))] public interface IService { [OperationContract] int Add(int i, int j); } [ServiceContract] public interface ICallback { [OperationContract] void Percent(int x); }
服务端实现了Iservice服务接口
//ConcurrencyMode.Multiple确保在回调时并发执行 [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] public class Service : IService { public int Add(int a, int b) { int i = 10; // simulate the processing progress while (i <= 100) { //通过OperationContext获取调用上下文,从中取出客户端的ICallback接口实现 ICallback callback = OperationContext.Current.GetCallbackChannel(); //调用回调方法,更新进度 callback.Percent(i); i = i + 10; Thread.Sleep(500); } return a + b; } }
下面是服务端的Host,注意要用到wsDualHttpBinding,实现双向通信:
下面是客户端的ICallback回调接口实现:
public void Percent(int x) { //打印当前从服务端传回的进度 Console.WriteLine(string.Format("Percent: {0}\t", x)); }
客户端调用:
static void Main(string[] args) { //新建一个回调实例 ICallback callback = new Callback(); //创建调用上下文 InstanceContext context = new InstanceContext(callback); //创建WSDualHttpBinding绑定 WSDualHttpBinding binding = new WSDualHttpBinding(); //Guid保证了在一个机器上同时运行多个客户端时服务端回调地址不会冲突 binding.ClientBaseAddress = new Uri(string.Format("{0}{1}", "http://localhost:7799/Callback/", Guid.NewGuid().ToString())); using (DuplexChannelFactorychannel = new DuplexChannelFactory (context, binding, new EndpointAddress("http://localhost:9888/Service"))) { IService proxy = channel.CreateChannel(); Console.WriteLine("output is :" + proxy.Add(9, 10)); Console.Read(); } }
源码地址:
https://github.com/boydwang/LearningNote/tree/master/WCFCallBack