the message pattern for WCF is divided into:
1. Request/Reply mode
2. Unidirectional mode
3. Duplex mode
where, request/reply mode, in Blog:
WCF Getting Started tutorial one (hands-on new first WCF program and deploy)
WCF Getting Started Tutorial II
is described in detail here: one-way mode and duplex mode.
1. First, create a WCF application first:
After the creation is complete, the directory is as follows:
2, delete IService1.cs and serivce1.svc, or modify the name: Calculateservice.svc and ICalculateService.cs, the following is displayed:
3. The contents of ICalculateService.cs file are as follows:
Using system;using system.collections.generic;using system.linq;using system.runtime.serialization;using System.servicemodel;using system.servicemodel.web;using system.text;namespace WcfDuplexTest{//Note: Use Rename on the Refactor menu command, you can change the code and the interface name "IService" in the configuration file at the same time. [ServiceContract (Namespace = "Http://blog.csdn.net/jiankunking", SessionMode = sessionmode.required, CallbackContract = typeof (Icalculatorduplexcallback))] public interface Icalculateservice {[Operationcontrac T (IsOneWay = true)] void GetData (string value); [OperationContract] Compositetype Clear (); TODO: Add your service operation here}/* We can see that it has a icalculatorduplexcallback interface because it is marked as callbackcontract in ServiceContract = typeof (ICa Lculatorduplexcallback), so it is used for client callbacks. * Meaning, the server can send the data to the client through the method in this interface, the client only need to implement this interface, can receive the message sent by the server. */public interface Icalculatorduplexcallback {[OperationContract (IsOneWay = true)] void COMPLEXCALCU Late (string result); [OperationContract]String Getcomplexcalculateresult (string value); Add the composite type to the service operation using the data contract described in the following example [DataContract] public class Compositetype {bool Boolvalue = true; String stringvalue = "Hello"; [DataMember] public bool Boolvalue {get {return boolvalue;} set {boolvalue = value;} } [DataMember] public string StringValue {get {return stringvalue;} set {stringvalue = value;} } }}
4. The contents of the Calculateservice.svc file:
Using system;using system.collections.generic;using system.linq;using system.runtime.serialization;using System.servicemodel;using system.servicemodel.web;using system.text;namespace WcfDuplexTest{/* ServiceContract SessionMode for enumeration on contract, 3: Allowed: Specifies that the contract will never support session Required: Specifies that the contract must be session bound, otherwise an exception is thrown. BasicHttpBinding does not support sessions, so it will be abnormal when using BasicHttpBinding; NotAllowed: Specifies that the contract never supports a binding that initiates a session. *///NOTE: Using the rename command on the Refactor menu, you can change the class name "Service" in code and configuration files at the same time. [ServiceBehavior (InstanceContextMode = instancecontextmode.persession, ConcurrencyMode = ConcurrencyMode.Multiple)] public class Calculateservice:icalculateservice {//declares an object for an Icalculatorduplexcallback interface icalculatorduple Xcallback callback = null; Construction method of the Calculateservice class public Calculateservice () {//Instantiate a Icalculatorduplexcallback callback = Operationcontext.current.getcallbackchannel<icalculatorduplexcallback> (); } public void GetData (string value) { The server invokes the client's Complexcalculate method Callback.complexcalculate (value); Public Compositetype Clear () {Compositetype composite = new Compositetype (); Composite. Boolvalue = false; The server invokes the client's Getcomplexcalculateresult method composite. stringvalue = "Test callback client with return value method \ r \ n" + callback. Getcomplexcalculateresult ("Client method: Getcomplexcalculateresult"); return composite; } }}
5. Modify the configuration file for Web. config
<?xml version= "1.0" encoding= "Utf-8"?><configuration> <system.web> <compilation debug= "true" targetframework= "4.0"/> </system.web> <system.serviceModel> <!--WCF applications the Services node needs to manually add the--& Gt <services> <service name= "Wcfduplextest.calculateservice" > <endpoint address= "" binding= "wsdual Httpbinding "contract=" Wcfduplextest.icalculateservice "> <identity> <dns value=" localhost " /> </identity> </endpoint> <endpoint address= "Mex" binding= "mexHttpBinding" cont ract= "IMetadataExchange"/> 6. New WinForm Client for testing7. Add a service-side reference:
8, the client code is as follows:
Using system;using system.collections.generic;using system.componentmodel;using system.data;using System.Drawing; Using system.linq;using system.text;using system.windows.forms;using system.servicemodel;using Formtest.calculateservice;namespace formtest{public partial class Form1:form {public Form1 () { InitializeComponent (); private void Button1_Click (object sender, EventArgs e) {//Construct InstanceContext to handle Messages on callback interface InstanceContext InstanceContext = new InstanceContext (new CallbackHandler ()); Create a client calculateservice.calculateserviceclient client = new Calculateservice.calculatese Rviceclient (InstanceContext); Client. GetData ("Client incoming parameter Test GetData"); MessageBox.Show ("GetData Call complete! "); The purpose of the WCF data contract is compositetype composite = client. Clear (); MessageBox.Show ("Clear call succeeded \ r \ n" + composite.) StringValue); }}///<summary>//I think I can find the Icalculatorduplexcallback interface in the server, who knows the interface of the server Icalculatorduplexcallback//is ical The form of Culateservicecallback appears on the client's///</summary>//Modify the notification thread of the callback callback function, changing it to execute in a non-UI thread. In WCF, you can control this behavior by Callbackbehaviorattribute in the client callback function class//To resolve the UI deadlock problem [Callbackbehavior (ConcurrencyMode = Concurrencymode.reentrant, Usesynchronizationcontext = False)] public class CallbackHandler:CalculateService.ICalcul ateservicecallback {public void complexcalculate (string result) {MessageBox.Show (result). ToString ()); public string Getcomplexcalculateresult (string result) {return result; } }}
Small bet
Need to be aware of deadlock issues in WCF callbacks
1, if the operation exposed in WCF, there is no return value, then you can set the callback operation
Isoneway=true, which releases the service instance immediately after the callback, without waiting for the client to respond to the message, or to avoid deadlocks.
2, if the operation exposed in WCF, there is a return value, you need to pass, modify the service ServiceBehavior ConcurrencyMode for reentrant or multiple.
At this point, the deadlock problem on the service side has been fixed.
The following need to consider the client deadlock problem
The deadlock problem of the client, which is controlled by the Callbackbehaviorattribute in the client callback function class
Deadlock specific analysis can be consulted: Click to open the link
Demo code: Click to open the link
Copyright: jiankunking Source: http://blog.csdn.net/jiankunking This article is copyright to the author and Csdn, Welcome to reprint, but without the consent of the author must retain this paragraph, and in the article page obvious location to the original connection.
WCF Duplex Mode