Duplex Communication


The next sample application shows how a duplex communication can be done between the client and the service. The client starts the connection to the service. After the client connected to the service, the service can call back into the client.

For duplex communication, a contract must be specified that is implemented in the client. Here the contract for the client is defined by the interface IMyMessageCallback. The method implemented by the client is OnCallback(). The operation has the operation contract setting IsOneWay=true applied. This way, the service doesn’t wait until the method is successfully invoked on the client. By default, the service instance can only be invoked from one thread (see the ConcurrencyMode property of the service behavior that is, by default, set to ConcurrencyMode.Single).

If the service implementation now does a callback to the client and waits to get an answer from the client, the thread getting the reply from the client must wait until it gets a lock to the service object. Because the service object is already locked by the request to the client, a deadlock occurs. WCF detects the deadlock and throws an exception. To avoid this situation, you can change the ConcurrencyMode property to a value Multiple or Reentrant. With the setting Multiple, multiple threads can access the instance concurrently. Here you have to implement locking on your own. With the setting Reentrant, the service instance keeps single threaded, but allows answers from callback requests to reenter the context. Instead of changing the concurrency mode, you can also specify the IsOneWay property with the operation contract. This way, the caller does not wait for a reply. Of course, this setting is only possible if return values are not expected.

The contract of the service is defined by the interface IMyMessage. The callback contract is mapped to the service contract with the CallbackContract property of the service contract definition.

  public interface IMyMessageCallback {    [OperationContract(IsOneWay=true)]    void OnCallback(string message); } [ServiceContract(CallbackContract=typeof(IMyMessageCallback))] public interface IMyMessage {    [OperationContract]    void MessageToServer(string message); } 

The class MessageService implements the service contract IMyMessage. The service writes the message from the client to the console. To access the callback contract, you can use the OperationContext class. OperationContext.Current returns the OperationContext that is associated with the current request from the client. With the OperationContext, you can access session information, message headers and properties, and in case of a duplex communication the callback channel. The generic method GetCallbackChannel() returns the channel to the client instance. This channel can then be used to send a message to the client by invoking the method OnCallback() that is defined with the callback interface IMyMessageCallback. To demonstrate that it is also possible to use the callback channel from the service independent of the context from the context of the method, a new thread that receives the callback channel is created. The new thread sends again messages to the client by using the callback channel.

  public class MessageService : IMyMessage {    public void MessageToServer(string message)    {       Console.WriteLine("message from the client: {0}", message);       IMyMessageCallback callback =             OperationContext.Current.GetCallbackChannel<IMyMessageCallback>();       callback.OnCallback("message from the server");       new Thread(ThreadCallback).Start(callback);    }    private void ThreadCallback(object callback)    {       IMyMessageCallback messageCallback = callback as IMyMessageCallback;       for (int i = 0; i < 10; i++)       {          messageCallback.OnCallback("message " + i.ToString());          Thread.Sleep(1000);       }    } } 

Hosting the service is no different from the way it was with the previous samples, so it is not shown here. However, for duplex communication you must configure a binding that supports a duplex channel. One of the bindings supporting a duplex channel is wsDualHttpBinding, which is configured in the application configuration file:

 <?xml version="1.0" encoding="utf-8" ?> <configuration>   <system.serviceModel>     <services>       <service name="Wrox.ProCSharp.WCF.MessageService">         <endpoint contract="Wrox.ProCSharp.WCF.IMyMessage"             binding="wsDualHttpBinding"/>       </service>     </services>   </system.serviceModel> </configuration>

With the client application the callback contract must be implemented as shown here with the class ClientCallback that implements the interface IMyMessageCallback.

  class ClientCallback : IMyMessageCallback {    public void OnCallback(string message)    {       Console.WriteLine("message from the server: {0}", message);    } } 

With a duplex channel, you cannot use the ChannelFactory to initiate the connection to the service as was done previously. To create a duplex channel, you can use the DuplexChannelFactory class. This class has a constructor with one more parameters in addition to the binding and address configuration. This parameter specifies an InstanceContext that wraps one instance of the ClientCallback class. When passing this instance to the factory, the service can invoke the object across the channel. The client just needs to keep the connection open. If the connection is closed, the service cannot send messages across it.

  WSDualHttpBinding binding = new WSDualHttpBinding(); EndpointAddress address =       new EndpointAddress("http://localhost:8080/service1"); ClientCallback clientCallback = new ClientCallback(); InstanceContext context = new InstanceContext(clientCallback); DuplexChannelFactory<IMyMessage> factory =    new DuplexChannelFactory<IMyMessage>(context, binding, address); IMyMessage messageChannel = factory.CreateChannel(); messageChannel.MessageToServer("From the client"); 

Duplex communication is done by starting the service host and the client application.




Professional C# 2005 with .NET 3.0
Professional C# 2005 with .NET 3.0
ISBN: 470124725
EAN: N/A
Year: 2007
Pages: 427

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net