Search code examples
c#multithreadingasynchronousasync-awaitconcurrency

Where to put await in an async method in this specific scenario


I was dicussing this with a colleague, and none of us were sure about it. Given these two methods using the asynchronous framework in C#, will there be a difference in performance between the two?

public async Task<ReadRespone> MethodA(ReadRequest request)
{
    var response = SynchronousReadThatTakesAWhileToExecute();
    return await Task.FromResult(new ReadResponse(response));
}

public async Task<ReadResponse> MethodB(ReadRequest request)
{
    var response = await Task.FromResult(SynchronousReadThatTakesAWhileToExecute());
    return new ReadResponse(response);
}

I was thinking that MethodA would perform the slow method syncronously, and then, since it only uses await for a trivial constructor, would in practice be a synchronous method, which would block execution for other threads. My colleague argued that both would be the same in practice, and that an async method should always return a task (but I'm thinking that await already "unboxes" the Task, and that an asynch method only needs to have an await Task somewhere in it to be correct).

Thanks


Solution

  • As others have pointed out, Task.FromResult() doesn't really work like that. It takes a value and returns a completed task, with the value. You want to use Task.Run or TaskFactory.StartNew.

    public async Task<ReadResponse> Foo(ReadRequest request)
    {
        var result = await Task.Run(SynchronousReadThatTakesAWhileToExecute);
        return new ReadResponse(result);
    }
    

    Notice the lack of brackes after SynchronousReadThatTakesAWhileToExecute. This is because I am not calling the function directly but passing it to Task.Run instead. This is functionally equivalent to passing () => SynchronousReadThatTakesAWhileToExecute() to Task.Run as an argument.

    Editing my response so that it actually answers the question: The provided two options are pretty much identical performance-wise.