Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF ServiceContract's method returning Task<T> and timeout

Tags:

wcf

I'm new to WCF. I'm making a service in which I need to compute a lengthy operation. Since the method is lengthy I thought I could make the operation async by returning a Task. But it does not work. I'm still getting a Timeout exception. Sample code (not my actual code) demonstrating my problem below:

[ServiceContract]
public interface ICalculator
{
   [OperationContract] 
   Task<double> ComputePiAsync(ulong numDecimals);
}

internal class Calculator : ICalculator
{
    public async Task<double> ComputePiAsync(ulong numDecimals)
    {
        return await SomeVeryVeryLongWayOfComputingPi(numDecimals);
    }
}

// server
using (var host = new ServiceHost(typeof(Calculator), new Uri("net.pipe://localhost")))
{
    host.AddServiceEndpoint(typeof(ICalculator), new NetNamedPipeBinding(), "Calculator");
    host.Open();

    Console.WriteLine("Service is running. Press <ENTER> to exit.");
    Console.ReadLine();

    host.Close();
}

// client
var factory = new ChannelFactory<ICalculator>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/Calculator"));
var calculator = factory.CreateChannel();
await calculator.ComputePiAsync(numDecimals); // <--- this call takes longer than 1 minute and I'm getting a timeout here.

So what should I do in order to call a lengthy operation on my service and wait for the result asynchronously ? Increase timeout ? If I increase the operation timeout, what's the point of having the method return a Task ?

like image 888
user1968335 Avatar asked Jul 25 '13 09:07

user1968335


1 Answers

Since the method is lengthy I thought I could make the operation async

Hold on, slow down - you are mixing up asynchrony with network operation timeout.

Lets consider asynchrony first:

1. Using async/await to asynchronously call a WCF service from client

async/await on client side helps us to write asynchronous program so that the application remains responsive - in case of say WPF/WinForm we don't want to freeze the UI by calling a WCF service synchronously on the UI thread. Instead we can call it asynchronously using async/await. The magic here is that this is complete client side functionality - meaning the service need not be asynchronous or need not return a Task - all you have to to is while creating the service reference(proxy) you have to tell Visual Studio to generate Task based async operations - and you can then use async/await on your client.

2. Then What is the need for async/await on service side?

The service itself may perform some I/O like query some data source or in-turn call another service. By using async/await on service side - the service can perform these operations asynchronously - without blocking any service threads. Which means service has more free threads to serve new clients - hence service scales much better.

Now, above two should not be confused with long running service operation

When your service takes long to get results, you are dealing with network timeouts. You cannot and should not try to keep a network connection indefinitely open without any activity. WCF helps you with this by configuring various timeouts. If your service method takes long to respond, you will have to increase those timeouts. You can consider using WCF callback contracts if you want to report progress back to the client. If that does not suffice your requirement then re-design your service such that client can initiate the long running process and then call another method on the service to query the status.

like image 115
YK1 Avatar answered Oct 19 '22 06:10

YK1