1

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

Eagle
  • 451
  • 2
  • 5
  • 14
  • https://stackoverflow.com/questions/21033150/any-difference-between-await-task-run-return-and-return-task-run – STALER Jul 02 '20 at 04:49
  • Do 1., not 2. It doesn't not add anything to await a task you just ran. – Enigmativity Jul 02 '20 at 06:13
  • Take a look at this: [Eliding Async and Await](https://blog.stephencleary.com/2016/12/eliding-async-await.html). Quoting from the article: *"Do not elide by default. 1. Use the async and await for natural, easy-to-read code. 2. Do consider eliding when the method is just a passthrough or overload."* – Theodor Zoulias Jul 02 '20 at 08:08

1 Answers1

3

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);
    }
}
TheGeneral
  • 79,002
  • 9
  • 103
  • 141