Home > Enterprise >  Best way to handle sync code within an async method
Best way to handle sync code within an async method

Time:01-19

I am implementing a message dispatcher/handler where each handler must implement an interface like Task<Result> HandleAsync(IEvent myevent)

For example:

public async Task<Result> HandleAsync(CustomerChangedEvent ev)
{
    await DoSomethingAsync();
    ...
    return myResult;
}

But sometimes I need to run something which is sync only so no await and that as you know will give you a compiler warning. What I have done is to add await Task.CompletedTask; in my code. Works fine AFAIK but is there any downside doing this?

Another alternative is to drop the async but in that case I need to return a Task, right? For example to return Task.FromResult(myResult).

Is there any benefits for one method over another (or different approach), especially from a performance perspective (like is there any substantial cost to declare a method as async. Personally, I prefer the first alternative. For some reason I find return Task.FromResult harder to read and understand even if the first method adds a dummy command.

CodePudding user response:

Actually, I recommend ignoring the compiler warning in this case. Most of the time this compiler warning is useful, so I don't recommend disabling it solution-wide, just here.

The problem with Task.FromResult is that you also have to handle exceptions - catch them and return Task.FromException (or Task.FromCanceled). The problem with await Task.CompletedTask is that it's an unnecessarily expensive noop.

So I recommend ignoring the compiler warning. If you have to do this in several places, you can write a simple helper type like this.

CodePudding user response:

I'm guessing the compiler warning you are getting is that you're not using await in an async method.

Using await Task.CompletedTask does nothing useful other than suppress the warning. The await keyword does nothing when it acts on a completed Task. You get no benefit, but there is still the overhead of managing an async method and all the background stuff that has to happen to accommodate it.

If you have to return a Task<Result>, but are not doing anything asynchronously, then drop the async and return Task.FromResult(myResult).

  • Related