locked
WCF operation timeouts RRS feed

  • Question

  • Hi,

    I have a Console application where I am hosting the WCF service. I use NETCP binding. This service can receive concurrently receive maximum request (say 10000+). This service is implemented in Async mode so that client does not need to wait till the service process that request. I use "LimitedConcurrencyLevelTaskScheduler" custom TaskScheduler, so that only one task is processed at a time and the rest are queued. When iterating for 10000 records, I get the operation timeout error even though I am closing the proxy in the call back method. If I set the "SendTimeOut" value to 10 min, then its work. But I want to understand why I get the time out error even if I close the proxy immediately in the callback (When “SendTimeOut” is set to default value). Am I missing something? I guess, this behavior will not make any difference with setting the different InstanceContext modes. Since this will only manage the service instance. Also please guide me if this approach is perfect for asynchronous execution.

    NOTE: All my callback tasks execute synchrously.

    Below is my service definition

       [ServiceContract]
        public interface ISampleTaskAsync
        {
            [OperationContract(AsyncPattern = true)]
            IAsyncResult BeginDoWork(int count, AsyncCallback callback, object state);
    
            ClientData EndDoWork(IAsyncResult result);
        }
    
        [DataContract]
        public class ClientData
        {
            [DataMember]
            public int Id {get;set;}
    
            [DataMember]
            public ExecutionStatus Status{get;set;}
        }
    
        [DataContract]
        public enum ExecutionStatus
        {
            [EnumMember]
            Completed = 1,
    
            [EnumMember]
            InProgress
        }
    
        public static class Shared
        {
            public static string EndPointAddress = "net.tcp://localhost:8765/TestService";
        }

    Below is my service implementation

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] public class Service : ISampleTaskAsync { public IAsyncResult BeginDoWork(int count, AsyncCallback callback, object state) {

    // Only one task is executed at a time

    LimitedConcurrencyLevelTaskScheduler lcts = new LimitedConcurrencyLevelTaskScheduler(1); TaskFactory factory = new TaskFactory(lcts); // Create a task to do the work var task = factory.StartNew<ClientData>((o) => { // Spend some time System.Threading.Thread.Sleep(new TimeSpan(0, 0, 5)); Data.InsertserverData(count); ClientData data = new ClientData(); data.Id = count; data.Status = ExecutionStatus.InProgress; return data; }, state); return task.ContinueWith(res => { callback(task); }, TaskContinuationOptions.ExecuteSynchronously); } public ClientData EndDoWork(IAsyncResult result) { // If an exception occured in your worker it will show up here Task<ClientData> t = result as Task<ClientData>; if (t.Exception == null) return t.Result; else return null; } }

    Below is my code where i am hosting my service. For simplicity and testing, i am using the console application to host my service.

      ServiceHost host = new ServiceHost(typeof(Service));
                host.AddServiceEndpoint(typeof(ISampleTaskAsync), new NetTcpBinding(), Shared.EndPointAddress);//"http://localhost:1111/Myservices.svc");
                ServiceThrottlingBehavior throttleBehavior = new ServiceThrottlingBehavior();
                throttleBehavior.MaxConcurrentCalls = int.MaxValue;
                throttleBehavior.MaxConcurrentInstances = int.MaxValue;
                throttleBehavior.MaxConcurrentSessions = int.MaxValue;
                host.Description.Behaviors.Add(throttleBehavior);
                host.Open();
                ChannelDispatcher dispatcher = host.ChannelDispatchers[0] as ChannelDispatcher;
                Console.WriteLine(" MaxConcurrentCalls - {0}", dispatcher.ServiceThrottle.MaxConcurrentCalls);
                Console.WriteLine(" MaxConcurrentInstances - {0}", dispatcher.ServiceThrottle.MaxConcurrentInstances);
                Console.WriteLine(" MaxConcurrentSessions - {0}", dispatcher.ServiceThrottle.MaxConcurrentSessions);
                Console.WriteLine("Service started");
                Console.Read();

    Here is my proxy code

    class Proxy : ClientBase<AsyncTest.ISampleTaskAsync>, AsyncTest.ISampleTaskAsync
        {
    
            public Proxy(NetTcpBinding binding, EndpointAddress endpoint)
                : base(binding, endpoint)
            { }
    
            public IAsyncResult BeginDoWork(int count, AsyncCallback callback, object state)
            {
                return base.Channel.BeginDoWork(count,callback,state);
            }
    
            public AsyncTest.ClientData EndDoWork(IAsyncResult result)
            {
                return base.Channel.EndDoWork(result);
            }
        }

    Here is my client code

    static void Main(string[] args)
            {
                var binding = new NetTcpBinding();
                binding.SendTimeout = new TimeSpan(0, 5, 0);
                var endpoint = new EndpointAddress(Shared.EndPointAddress);
               
                LimitedConcurrencyLevelTaskScheduler lcts = new LimitedConcurrencyLevelTaskScheduler(1);
                TaskFactory<ClientData> factory = new TaskFactory<ClientData>(lcts);
                for (int i = 0; i < 10000; i++)
                {
                    Proxy proxy = new Proxy(binding, endpoint);
                    Data.InsertClientData(i);
                    Temp temp = new Temp();
                    temp.count = i;
                    temp.P = proxy;
                    var task = factory.FromAsync(proxy.BeginDoWork, proxy.EndDoWork, i, temp);
                    task.ContinueWith((t) =>
                    {
                        var state = t.AsyncState as Temp;
                        if (t.Exception == null)
                            Console.WriteLine("Count -" + state.count);
                        else
                            Console.WriteLine("Excep {0}", t.Exception);
                        state.P.Close();
                    },TaskContinuationOptions.ExecuteSynchronously);
                }
               
               
                Console.WriteLine("Service call ended");
                Console.Read();
            }
    
            class Temp
            {
                public int count;
                public Proxy P;
            }

    Thanks,

    Mallikarjun


    Below is the error message

    This request operation sent to net.tcp://mallikarjun-pc:8765/TestService did not receive a reply within the configured timeout (00:05:00).  The time allotted to this operation may have been a portion of a longer timeout.  This may be because the service is still processing the operation or because the service was unable to send a reply message.  Please consider increasing the operation timeout (by casting the channel/proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client.


    • Edited by Mallikarjun Gouda Thursday, December 20, 2012 8:56 AM error message missing
    Thursday, December 20, 2012 8:53 AM