WCF Threading with ConcurrencyMode

Threading operation calls within a single InstanceContext in WCF is configured by setting the ServiceBehavior attribute’s ConcurrencyMode property to one of the following enumeration values:

  • Single Single threaded. subsequent calls are placed in a queue until the service lock is released. Can cause deadlock when calling other services from the service.
  • Reentrant Single threaded but accepts reentrant/returning calls made from the service to other services. Helps to avoid deadlock situations.
  • Multiple Multi threaded. Synchronization and consistency is the service own responsibility. May be hard to manage in code.

The example below builds on the ThrottlingService but without serviceThrottling enabled. We use netTcpBinding and a PerSession InstanceContext to handle all operation calls within one session and one instance of the service. Since the default ConcurrencyMode is Single, all subsequent async operation calls are queued up and handled consecutive. If we specify Multiple as our concurrency mode, as show below, all operation calls, up to MaxConcurrentCalls, are handled on different threads and returned as soon as possible.

using System.ServiceModel;
using System.Threading;
 
namespace WcfServiceLibrary.Throttling
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
        ConcurrencyMode = ConcurrencyMode.Multiple)]
    internal class ThrottlingService : IThrottlingService
    {
        #region IThrottlingService Members
 
        public int Call()
        {
            // take a nap for a few seconds
            Thread.Sleep(3000);
 
            // return the instance hash
            return GetHashCode();
        }
 
        #endregion
    }
}

On the client side we invoke the Call() operation a couple of times async and write the instance hash of the service to the console.

using System;
using ThrottlingServiceConsole.ThrottlingServiceReference;
 
namespace ThrottlingServiceConsole
{
    internal class Program
    {
        private static void Main()
        {
            var channel = new ThrottlingServiceClient(
                "WSHttpBinding_IThrottlingService"
                );
 
            channel.CallCompleted += ChannelCallCompleted;
 
            try
            {
                for (int i = 0; i < 9; i++)
                {
                    channel.CallAsync();
                    Console.WriteLine("Call {0} made", i);
                }
 
                Console.ReadLine();
                channel.Close();
            }
            catch (Exception exception)
            {
                channel.Abort();
            }
        }
 
        private static void ChannelCallCompleted(
            object sender, CallCompletedEventArgs e)
        {
            Console.WriteLine(
                "Call returned at {0} from instance {1}",
                DateTime.Now.ToLongTimeString(),
                e.Result);
        }
    }
}

Multiple operation calls are now handled in parallel.

WCF ConcurrencyMode Multiple Console

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>