双工模式的特点
1.无论使用单向消息发送还是请求/答复消息发送方式,服务和客户端均能够独立地向对方发送消息。对于必须直接与客户端通信或向消息交换的任意一方提供异步体验(包括类似于事件的行为)的服务来说,这种双向通信形式非常有用
2.若要设计双工协定,还必须设计回调协定,并将该回调协定的类型分配给标记服务协定的ServiceContractAttribute 属性(attribute)的CallbackContract 属性(property)。
3.若要实现双工模式,您必须创建第二个接口,该接口包含服务端在客户端调用的方法声明
eg:
1.在IService1中
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace WcfServiceLibrary2 { [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode = SessionMode.Required, CallbackContract = typeof(ICalculatorDuplexCallback))] public interface ICalculatorDuplex { [OperationContract(IsOneWay = true)] void Clear(); [OperationContract(IsOneWay = true)] void AddTo(double n); [OperationContract(IsOneWay = true)] void SubtractFrom(double n); [OperationContract(IsOneWay = true)] void MultiplyBy(double n); [OperationContract(IsOneWay = true)] void DivideBy(double n); } public interface ICalculatorDuplexCallback { [OperationContract(IsOneWay = true)] void Equals(double result); [OperationContract(IsOneWay = true)] void Equation(string eqn); } }
CallbackContract = typeof(ICalculatorDuplexCallback))]表示服务端从客户端调用的是ICalculatorDuplexCallback这个接口,这个接口的实现可以在客户端的cs中实现
2.在Service中
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace WcfServiceLibrary2 { [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] public class CalculatorService : ICalculatorDuplex { double result; string equation; ICalculatorDuplexCallback callback = null; public CalculatorService() { result = 0.0D; equation = result.ToString(); callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>(); } public void Clear() { callback.Equation(equation + " = " + result.ToString()); result = 0.0D; equation = result.ToString(); } public void AddTo(double n) { result += n; equation += " + " + n.ToString(); callback.Equals(result); } public void SubtractFrom(double n) { result -= n; equation += " - " + n.ToString(); callback.Equals(result); } public void MultiplyBy(double n) { result *= n; equation += " * " + n.ToString(); callback.Equals(result); } public void DivideBy(double n) { result /= n; equation += " / " + n.ToString(); callback.Equals(result); } } }
在app中,将binding更改<endpoint address="" binding="wsDualHttpBinding" contract="WcfServiceLibrary2.ICalculatorDuplex">
3.新建一个窗体应用程序,然后引用这个service,在progrom中
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using ConsoleApplication1.ServiceReference1; namespace ConsoleApplication1 { public class CallbackHandler : ICalculatorDuplexCallback { public void Equals(double result) { Console.WriteLine("Result({0})", result); } public void Equation(string eqn) { Console.WriteLine("Equation({0})", eqn); } } class Program { static void Main(string[] args) { //指定服务端调用客户端的方法 InstanceContext instanceContext = new InstanceContext(new CallbackHandler()); ServiceReference1.CalculatorDuplexClient client = new ServiceReference1.CalculatorDuplexClient(instanceContext); //加 double value = 100.00D; client.AddTo(value); //减 value = 50.00D; client.SubtractFrom(value); //乘 value = 17.65D; client.MultiplyBy(value); //除 value = 2.00D; client.DivideBy(value); //清除 client.Clear(); //关闭 Console.ReadLine(); client.Close(); } } }