Normally, the intended usage for Task.Run
is to execute CPU-bound code on a non-UI thread. As such, it would be quite rare for it to be used with an async
delegate, but it is possible (e.g., for code that has both asynchronous and CPU-bound portions).
However, that’s the intended usage. I think in your example:
var task = Task.Run(async () => { await Foo.StartAsync(); });
task.Wait();
It’s far more likely that the original author is attempting to synchronously block on asynchronous code, and is (ab)using Task.Run
to avoid deadlocks common in that situation (as I describe on my blog).
In essence, it looks like the “thread pool hack” that I describe in my article on brownfield asynchronous code.
The best solution is to not use Task.Run
or Wait
:
await Foo.StartAsync();
This will cause async
to grow through your code base, which is the best approach, but may cause an unacceptable amount of work for your developers right now. This is presumably why your predecessor used Task.Run(..).Wait()
.