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 ?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With