Eagle
Eagle

Reputation: 481

Async Method Call Non-Async Method Best Practices

For some reason I need to inherit a class to implement an Async method which is the below implementation that it is best practices

1.

protected override Task<TResult> OnExecuteAsync<TResult><TResult>()
{
        return Task.Run<TResult>(() => DoSomething());
}
protected override async Task<TResult> OnExecuteAsync<TResult><TResult>()
{
        return await Task.Run<TResult>(() => DoSomething());
}

I want to know which one is the best implementation?

Thank you

Upvotes: 1

Views: 398

Answers (1)

TheGeneral
TheGeneral

Reputation: 81483

In short, if the base class or interface is expecting a Task result and you have synchronous method and it doesn't need to run in a task, all you need to do is give it a pre-completed task.

The simplest thing to do, would be just leave the async keyword, return the result, and ignore (or pragma out) the warning. You do not need to spin-up a new task via Task.Run (this would be an inefficient way of achieving nothing). In this case the compiler automatically takes care of everything for you (albeit with a warning that you have nothing to await)

protected override async Task<TResult> OnExecuteAsync<TResult>()
{
    return DoSomething();
}

You could also use Task.FromResult to create the pre-completed task. The only caveat is if the consumer is calling await, in which case you should be nice and make sure any exceptions are returned on the resulting Task with Task.FromException. This is analogous to what the compiler generated IAsyncStateMachine implementation (async and await pattern) would automatically do.

protected override Task<TResult> OnExecuteAsync<TResult>()
{
    try
    {
        return Task.FromResult(DoSomething());
    }
    catch(exception ex)
    { 
        // place any exception on the returned task
        return Task.FromException<TResult>(ex);
    }
}

Upvotes: 3

Related Questions