Let's simplify your starting point down to:
public void Execute(Action action)
{
action();
}
Because you say the finally
isn't important.
Valid but pointless:
public async Task ExecuteAsync(Action action)
{
action();
}
This will be pretty much the same as doing:
public Task ExecuteAsync(Action action)
{
action();
return Task.FromResult(0);
}
That is, it'll do what the non-async was doing, and then return a "completed" Task so nothing is gained. It's worth noting though as it's often a valid part-way-point in moving from non-async to async.
Better:
public async Task ExecuteAsync(Action action)
{
await Task.Run(() => action());
}
Which in this case, because it's a single void-returning call can be simplified to:
public async Task ExecuteAsync(Action action)
{
await Task.Run(action);
}
Whether this is worth doing or not is another matter. This releases the current thread from being used, but transfers to another thread to do the work. If we're just going to await the result of this when it's called then we might as well just call the non-async version and be done with it. If however we're doing WaitAll
in the caller, or something else that hence benefits from this, then it could indeed be useful.
Potentially much better though is:
public async Task ExecuteAsync(Action action)
{
await actionAsync();
}
Here there's an Async version of the method we are calling, so we change to make use of that. Now, that could be just the same as the above if actionAsync
just spins up a thread or uses the thread pool. If however actionAsync
does something using asynchronous I/O then there's a much bigger benefit to this.
Note that in this case we could have just tail-called the Task we get:
public Task ExecuteAsync(Action action)
{
return actionAsync();
}
However, that wouldn't be the same if we needed something done after an await
within our method. E.g.:
public void Execute(Action action)
{
action();
otherAction();
}
Would have to become:
public async Task Exectute(Action action)
{
await actionAsync();
await otherActionAsync();
}
Or if otherAction
had no async version:
public async Task Exectute(Action action)
{
await actionAsync();
otherAction();
}