Wednesday 29 September 2010

Instancing and concurrency in WCF

It doesn’t take long for my head to explode when thinking about threading and there is no exception when it comes to WCF. Here are a few notes on some of the main points.

How a WCF service reacts when it comes to threading and concurrency issues is basically governed by 2 concepts associated with the ServiceBehaviourAttribute: how the service is instantiated (e.g. as a singleton) through the use of the InstanceContextMode enumeration, and whether the service supports single-threaded or multi-threaded access through the use of the ConcurrencyMode enumeration.

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,
    ConcurrencyMode=ConcurrencyMode.Multiple, 
    UseSynchronizationContext=false)]
public class MessagingService : IMessagingService
{
 // other code here...
}

Instancing with the InstanceContextMode enumeration

InstanceContextMode  specifies the number of service instances available for handling calls that are contained in incoming messages.It therefore controls how service instances are allocated in response to client calls. InstanceContextMode can be set to the following values:

  • Single – One service instance is allocated for all client calls.
  • PerCall – One service instance is allocated for each client call.
  • PerSession – One service instance is allocated for each client session.

The default setting for InstanceContextMode is PerSession.

Note that when InstanceContextMode is set to PerCall, the ConcurrencyMode setting is ignored because each client call is routed to a new service instance. Only one thread is running in a service instance at one time.

Also note that when InstanceContextMode is set to PerCall, a new service instance is created for each client call and the instance is destroyed when the client call completes. In this case there are no synchronisation issues because each client call gets its own service instance.

If InstanceContextMode is set to Single the service can only process one message at a time unless you set the ConcurrencyMode to Multiple.

Concurrency with the ConcurrencyMode enumeration

ConcurrencyMode controls how multiple threads are allowed into the service at one time. ConcurrencyMode can be set to one of the following values:

  • Single – One thread can enter the service at one time.
  • Reentrant – One thread can enter the service at one time but callbacks are allowed.
  • Multiple – Multiple threads can enter the service at one time.

The default setting for ConcurrencyMode is Single. Setting ConcurrencyMode to single allows you to share service instances across multiple clients.

MSDN documentation states that the default value was chosen so that developers do not have to think about synchronisation by default.

Note that when the ConcurrencyMode is set to Multiple, multiple client calls can get through but it is the developer who is responsible for synchronising access to shared data.

The following table shows when an operation can be invoked while another one is in progress:

ConcurrencyMode Value Can a new operation be invoked?
Single Never
Reentrant Only while invoking another service or a callback
Multiple Always

 

Using the SynchronizationContext

In the C# example at the top of the page there is another property of the service behaviour attribute that is being used: UseSynchronizationContext. This property is of particular use if the service is being invoked from Windows clients (Win forms or WPF) and especially if callbacks are being used.

This is quite a complex topic which is covered in detail here.

See also

MSDN documentation:

Wednesday 29 September 2010