WCF duplex mode and wcf duplex mode
The message mode of WCF is divided:
1. Request/reply Mode
2. unidirectional mode
3. duplex mode
The request/reply mode is shown in the blog:
WCF getting started tutorial 1 (create and deploy the first WCF Program)
WCF tutorial 2
This section describes the unidirectional mode and duplex mode in detail.
1. First, create a WCF application:
After creation, the directory is as follows:
2. Delete IService1.cs and Serivce1.svc, or change the name to CalculateService. svc and ICalculateService. cs. The following figure is displayed:
3. The content of the ICalculateService. cs file is 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 the "RENAME" command on the "refactoring" menu to change the Interface Name "IService" in the Code and configuration file at the same time ". [ServiceContract (Namespace = "http://blog.csdn.net/jiankunking", SessionMode = SessionMode. required, CallbackContract = typeof (Signature)] public interface ICalculateService {[OperationContract (IsOneWay = true)] void GetData (string value); [OperationContract] CompositeType Clear (); // TODO: add your service operation here}/* we can see that it has an ICalculatorDuplexCallback interface, because it is marked as CallbackCont in ServiceContract Ract = typeof (ICalculatorDuplexCallback), so it is used for client callback. * That is, the server can send data to the client through the method in this interface. The client only needs to implement this interface to receive messages sent from the server. */Public interface ICalculatorDuplexCallback {[OperationContract (IsOneWay = true)] void ComplexCalculate (string result); [OperationContract] string GetComplexCalculateResult (string value );} // use the data protocol described in the following example to add a composite type to the service operation [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. Content in 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 is used for enumeration on Contract. Three types: Allowed: specify that the protocol supports session Required permanently: specify that the Protocol must be bound to the session; otherwise, an exception is thrown. BasicHttpBinding does not support sessions. Therefore, when BasicHttpBinding is used, an exception occurs. NotAllowed: specifies that the Protocol will never support binding sessions. * // Note: You can change the class name "Service" in the Code and configuration file by using the "RENAME" command on the "refactoring" menu ". [ServiceBehavior (InstanceContextMode = InstanceContextMode. perSession, ConcurrencyMode = ConcurrencyMode. multiple)] public class CalculateService: ICalculateService {// object that declares a callback interface ICalculatorDuplexCallback callback = null; // the construction method of the CalculateService class public CalculateService () {// instantiate an ICalculatorDuplexCallback callback = OperationContext. current. getCallbackChannel <ICalculatorDuplexCallback> ();} public void GetData (string value) {// The server calls the client's ComplexCalculate method callback. complexCalculate (value);} public CompositeType Clear () {CompositeType composite = new CompositeType (); composite. boolValue = false; // The server calls the client's GetComplexCalculateResult method composite. stringValue = "test callback client method with return value \ r \ n" + callback. getComplexCalculateResult ("client method: GetComplexCalculateResult"); return composite ;}}}
5. modify the configuration file of Web. config.
<? Xml version = "1.0" encoding = "UTF-8"?> <Configuration> <system. web> <compilation debug = "true" targetFramework = "4.0"/> </system. web> <system. serviceModel> <! -- For a WCF application, you need to manually add the services node --> <services> <service name = "WcfDuplexTest. calculateService "> <endpoint address =" "binding =" wsDualHttpBinding "contract =" WcfDuplexTest. ICalculateService "> <identity> <dns value =" localhost "/> </identity> </endpoint> <endpoint address =" mex "binding =" mexHttpBinding "contract =" IMetadataExchange" /> 6. Create a winform client for testing.
7. Add a server 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 button#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. calculateServiceClient (instanceContext); client. getData ("client passed in parameter test GetData"); MessageBox. show ("GetData call completed! "); // Use of the WCF data contract CompositeType composite = client. clear (); MessageBox. show ("Clear call successful \ r \ n" + composite. stringValue) ;}/// <summary> /// you can find the ICalculatorDuplexCallback interface on the server, who knows that the server interface ICalculatorDuplexCallback // appears in the form of ICalculateServiceCallback on the client // </summary> // modifies the notification thread of the callback function, change it to be executed in a non-UI thread. // In WCF, you can control this line in CallbackBehaviorAttribute In the callback function class of the client to solve the UI deadlock problem [CallbackBehavior (ConcurrencyMode = ConcurrencyMode. reentrant, UseSynchronizationContext = false)] public class CallbackHandler: CalculateService. ICalculateServiceCallback {public void ComplexCalculate (string result) {MessageBox. show (result. toString ();} public string GetComplexCalculateResult (string result) {return result ;}}}
Note:
Pay attention to the deadlock issue in the WCF callback.
1. If the operation exposed in WCF does not return a value, you can set the callback operation.
IsOneWay = true. In this way, the service instance will be released immediately after the callback, and the deadlock can be avoided without waiting for the client to respond to the message.
2. If the operation exposed in WCF has a return value, you must modify the ConcurrencyMode of ServiceBehavior of the Service to Reentrant or Multiple.
Now, the deadlock problem on the server is fixed.
The client deadlock issue needs to be considered below.
The client deadlock problem is caused by controlling this line in CallbackBehaviorAttribute of the client callback function class
For details about the deadlock analysis, refer to: Click to open the link.
Demo code: Click to open the link
Prompt message for server deadlock:
System. ServiceModel. FaultException '1 HResult =-2146233087 Message = this operation will be deadlocked because a reply cannot be received before the current mail is processed. If you want to allow unordered message processing, you can specify multiple concurrencymodes on ServiceBehaviorAttribute. Source = mscorlib Action = http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher/fault StackTrace: Server stack trace: in System. serviceModel. channels. serviceChannel. throwIfFaultUnderstood (Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter) in System. serviceModel. channels. serviceChannel. handleReply (ProxyOperationRuntime operation, ProxyRpc & rpc) in System. serviceModel. channels. serviceChannel. call (String action, Boolean oneway, ProxyOperationRuntime operation, Object [] ins, Object [] outs, TimeSpan timeout) in System. serviceModel. channels. serviceChannelProxy. invokeService (IMethodCallMessage methodCall, ProxyOperationRuntime operation) in System. serviceModel. channels. serviceChannelProxy. invoke (IMessage message) Exception rethrown at [0]: in System. runtime. remoting. proxies. realProxy. handleReturnMessage (IMessage reqMsg, IMessage retMsg) in System. runtime. remoting. proxies. realProxy. privateInvoke (MessageData & msgData, Int32 type) in FormTest. calculateService. ICalculateService. getData (Int32 value) in FormTest. calculateService. calculateServiceClient. getData (Int32 value) Location E: \ WorkSpace \ WorkSpaceTest \ WcfDuplexTest \ FormTest \ Service References \ CalculateService \ Reference. cs: the row number 124 is in FormTest. form1.button1 _ Click (Object sender, EventArgs e) Location E: \ WorkSpace \ WorkSpaceTest \ WcfDuplexTest \ FormTest \ Form1.cs: Row 27 in System. windows. forms. control. onClick (EventArgs e) in System. windows. forms. button. onClick (EventArgs e) in System. windows. forms. button. onMouseUp (MouseEventArgs mevent) in System. windows. forms. control. wmMouseUp (Message & m, MouseButtons button, Int32 clicks) in System. windows. forms. control. wndProc (Message & m) in System. windows. forms. buttonBase. wndProc (Message & m) in System. windows. forms. button. wndProc (Message & m) in System. windows. forms. control. controlNativeWindow. onMessage (Message & m) in System. windows. forms. control. controlNativeWindow. wndProc (Message & m) in System. windows. forms. nativeWindow. debuggableCallback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) in System. windows. forms. unsafeNativeMethods. dispatchMessageW (MSG & msg) in System. windows. forms. application. componentManager. system. windows. forms. unsafeNativeMethods. IMsoComponentManager. FPushMessageLoop (IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) in System. windows. forms. application. threadContext. runMessageLoopInner (Int32 reason, ApplicationContext context) in System. windows. forms. application. threadContext. runMessageLoop (Int32 reason, ApplicationContext context) in System. windows. forms. application. run (Form mainForm) in FormTest. program. main () Location E: \ WorkSpace \ WorkSpaceTest \ WcfDuplexTest \ FormTest \ Program. cs: the row number 18 is in System. appDomain. _ nExecuteAssembly (RuntimeAssembly assembly, String [] args) in System. appDomain. executeAssembly (String assemblyFile, Evidence assemblySecurity, String [] args) in Microsoft. visual Studio. hostingProcess. hostProc. runUsersAssembly () in System. threading. threadHelper. threadStart_Context (Object state) in System. threading. executionContext. runInternal (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in System. threading. executionContext. run (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in System. threading. executionContext. run (ExecutionContext executionContext, ContextCallback callback, Object state) in System. threading. threadHelper. threadStart () InnerException:
Copyright Disclaimer: Author: jiankunking Source: http://blog.csdn.net/jiankunking this article copyright to the author and CSDN a total, welcome to reprint, but without the author's consent must retain this statement, and in the Article Page clearly given the original connection.