Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Benefits from returning a "Task<int>" instead of an "int" in a WCF or WebAPI method (IIS)

Consider a time consuming synchronous method "Foo":

public int Foo(int id)
{
    // Do some expensive calculation
    return 42;
}

And a WCF Service hosted in IIS called "FooService" which calls "Foo":

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class FooService 
{
    public Task<int> GetFoo(int id)
    {
        return Task.Factory.StartNew(() => return Foo(id));
    }

    public int GetFoo2(int id)
    {
        return Foo(id);
    }
}

Do I get any benefits if I start and return a Task for Foo? Like - do I reduce load to the I/O Thread?

like image 241
Martin Brandl Avatar asked Mar 21 '23 11:03

Martin Brandl


1 Answers

Tasks in WCF provide a more convenient API than that of the APM pattern (BeginXX/EndXX). Why should you use asynchronous calls in WCF? Because, when done correctly, it would lead to a much better thread utilization, which in turn, allows your application to be more scalable.

On the client side, having a task-based service contract, makes it easier to call a service without blocking a thread, waiting for the call to return. Even if the operation is a synchronous, CPU-bound operation on the server side, the client side would benefit from having a task. Also, with tasks, it's very simple to make the call synchronous again by calling Task.Wait() or Task<T>.Result.

On the service side, a task-based operation can be useful in several scenarios:

  • You want to parallelize some CPU-bound actions
  • You're doing IO (e.g. calling another service, reading a file, etc.)
  • Any combination of the above

Every time a WCF operation is called, WCF grabs a thread from the thread-pool to handle the request. So there's no need to call StartNew, which queues an operation to the thread-pool (a completely redundant overhead):

public Task<int> GetFoo(int id)
{
    return Task.Factory.StartNew(() => return Foo(id));
}

Instead, you can use FromResult, which creates a completed task object:

public Task<int> GetFoo(int id)
{
    return Task.FromResult(new Foo(id));
}

Lastly, if none of the above use cases are relevant, and your client API needs to be synchronous, there's no point in using tasks.

like image 152
Eli Arbel Avatar answered Apr 07 '23 17:04

Eli Arbel