Search code examples
wcfsingletonsingle-threaded

Wcf Singleton with Single Thread


Can someone explain the issues that although I set both the InstanceContextMode and ConcurrencyMode to single with max concurrent calls instances and sessions set to 1 in ServiceThrottlingBehavior, I still found that at least 2 threads are processing the wcf requests?

Client Output:

Client name :kk Instance:1 Thread:13 Time:2013/12/30 12:17:56
Client name :kk Instance:1 Thread:12 Time:2013/12/30 12:17:57
Client name :kk Instance:1 Thread:13 Time:2013/12/30 12:17:58

Server Code:

    Uri httpUrl = new Uri("http://localhost:8010/MyService/HelloWorld");

    //Create ServiceHost
    ServiceHost host
    = new ServiceHost(typeof(ClassLibrary1.HelloWorldService), httpUrl);

    //Add a service endpoint
    host.AddServiceEndpoint(typeof(ClassLibrary1.IHelloWorldService)
    , new WSHttpBinding(), "");

    //Enable metadata exchange
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    ServiceThrottlingBehavior stb = new ServiceThrottlingBehavior
    {
        MaxConcurrentCalls = 1,
        MaxConcurrentInstances = 1 ,
        MaxConcurrentSessions = 1
    };
    host.Description.Behaviors.Add(smb);
    host.Description.Behaviors.Add(stb);
    //Start the Service
    host.Open();

Client Code:

    ServiceReference1.HelloWorldServiceClient obj = new ServiceReference1.HelloWorldServiceClient();
    for(int i=0;i<15;i++)
    {
       obj.Call(str);
       Thread.Sleep(1000);
    }

Service Code:

[ServiceContract]
public interface IHelloWorldService
{
    [OperationContract(IsOneWay=true)]
    void Call(string ClientName);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public class HelloWorldService : IHelloWorldService
{
    public static int i;

    public HelloWorldService()
    {
        i++;
    }
    public void Call(string ClientName)
    {
        Console.WriteLine("Client name :" + ClientName + " Instance:" + i.ToString() + " Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + " Time:" + DateTime.Now.ToString() + "\n\n");
    }

}

Solution

  • I'm not an expert on threading, but I'll take a stab at this and expand upon my comments.

    According to MSDN, ConcurrencyMode.Single means The service instance is single-threaded and does not accept reentrant calls. If the InstanceContextMode property is Single, and additional messages arrive while the instance services a call, these messages must wait until the service is available or until the messages time out.

    You're calling your service with a 1 second delay between each successive call. Your output shows this as well - each call is 1 second later than the immediately previous one.

    I believe the thread id is a red herring in this case, as I would expect the service to use an available thread from the thread pool. I don't see anything in the documentation that guarantees the same thread will be used every time, and it seems to me that would be an unreasonable expectation.

    If you're expecting a dedicated thread from the available threads, I don't think you can do that. If you're expecting the service to handle only one request at a time, the way you have it should do that.