15.02.2015 Views

C# 4 and .NET 4

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

1306 ❘ ChaPTer 43 windOws cOmmunicAtiOn fOundAtiOn<br />

duPleX CommuniCaTion<br />

The next sample application shows how a duplex communication can be done between the client <strong>and</strong> the<br />

service. The client starts the connection to the service. After the client connects to the service, the service<br />

can call back into the client.<br />

For duplex communication, a contract must be specified that is implemented in the client. Here the contract<br />

for the client is defined by the interface IMyMessageCallback. The method implemented by the client is<br />

OnCallback(). The operation has the operation contract setting IsOneWay=true applied. This way, the<br />

service doesn’t wait until the method is successfully invoked on the client. By default, the service instance<br />

can be invoked from only one thread (see the ConcurrencyMode property of the service behavior, which is,<br />

by default, set to ConcurrencyMode.Single).<br />

If the service implementation now does a callback to the client <strong>and</strong> waits to get an answer from the client,<br />

the thread getting the reply from the client must wait until it gets a lock to the service object. Because the<br />

service object is already locked by the request to the client, a deadlock occurs. WCF detects the deadlock<br />

<strong>and</strong> throws an exception. To avoid this situation, you can change the ConcurrencyMode property to the<br />

value Multiple or Reentrant. With the setting Multiple, multiple threads can access the instance<br />

concurrently. Here, you must implement locking on your own. With the setting Reentrant, the service<br />

instance stays single-threaded, but allows answers from callback requests to reenter the context. Instead<br />

of changing the concurrency mode, you can specify the IsOneWay property with the operation contract.<br />

This way, the caller does not wait for a reply. Of course, this setting is possible only if return values are not<br />

expected.<br />

The contract of the service is defined by the interface IMyMessage. The callback contract is mapped to the<br />

service contract with the CallbackContract property of the service contract definition:<br />

public interface IMyMessageCallback<br />

{<br />

[OperationContract(IsOneWay=true)]<br />

void OnCallback(string message);<br />

}<br />

[ServiceContract(CallbackContract=typeof(IMyMessageCallback))]<br />

public interface IMyMessage<br />

{<br />

[OperationContract]<br />

void MessageToServer(string message);<br />

}<br />

code snippet MessageService/IMyMessage.cs<br />

The class MessageService implements the service contract IMyMessage. The service writes the message<br />

from the client to the console. To access the callback contract, you can use the OperationContext class.<br />

OperationContext.Current returns the OperationContext that is associated with the current request<br />

from the client. With the OperationContext, you can access session information, message headers<br />

<strong>and</strong> properties, <strong>and</strong>, in the case of a duplex communication, the callback channel. The generic method<br />

GetCallbackChannel() returns the channel to the client instance. This channel can then be used to send<br />

a message to the client by invoking the method OnCallback(), which is defined with the callback interface<br />

IMyMessageCallback. To demonstrate that it is also possible to use the callback channel from the service<br />

independently of the completion of the method, a new thread that receives the callback channel is created.<br />

The new thread sends messages to the client by using the callback channel.<br />

public class MessageService: IMyMessage<br />

{<br />

public void MessageToServer(string message)<br />

{<br />

Console.WriteLine("message from the client: {0}", message);<br />

IMyMessageCallback callback =<br />

OperationContext.Current.<br />

www.it-ebooks.info

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!