0

I can perform an async action using Task.Run like so

await Task.Run(() =>
{
    DoSomeIOStuff();
    //throw new Exception("Custom Exception");
});

Sometimes I need a value returned

bool success = await Task.Run(() => ...

But sometimes I don't. I'd read that you should never have an async method with a return of void because, among other things, you can get lost exceptions (as outlined in this question). I tested the above Task.Run call with an exception in it and found that all of the data was handled, which meant that Task.Run was still returning a task even if I wasn't returning anything. Then I tried

var temp = await Task.Run(() =>

Which gives me an error that I can't assign void to a variable, which I would expect, but that leaves me wondering what Task.Run is returning. It's acting like it's returning a Task of nothing, so while I assume that's not what's happening, I haven't found any documentation about what it's doing. Any thoughts?

Community
  • 1
  • 1
cost
  • 4,420
  • 8
  • 48
  • 80
  • 1
    Spot the difference: [`Task`](http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx) vs [`Task`](http://msdn.microsoft.com/en-us/library/dd321424.aspx) – spender Jun 05 '14 at 00:30
  • 1
    It simply returns a non-generic `Task`.. which has no result. The reason behind not returning `void` is because `Task` wraps things like exceptions and whether there was a fault during execution. Returning `void` gives you none of that and assumes you handle it all in your method. – Simon Whitehead Jun 05 '14 at 00:30
  • @spender Even simpler than I realized – cost Jun 05 '14 at 00:32
  • @SimonWhitehead, it'd be great if you posted it as an answer, mate. – noseratio Jun 05 '14 at 00:34
  • @Noseratio Beaten to it by Servy. Not sure I can add much more :) – Simon Whitehead Jun 05 '14 at 00:38
  • @SimonWhitehead, right :) @cost, regarding the answer you linked, just beware of things like `Action a = async () => { /* ... */ }; await Task.Run(a);` This is where `async void` could give you troubles. – noseratio Jun 05 '14 at 00:40

1 Answers1

5

The overload of Task.Run that accepts an Action returns a Task. This is not a Task<T>, as it doesn't have a Result, but it's also not void. It's a task that can be completed, and can also propogate errors.

You can await it, and awaiting it results in an expression that has no value (i.e. void), meaning you can't assign it to anything. If Run returned void instead of Task *then you wouldn't have been able to await it in the first place.

Servy
  • 202,030
  • 26
  • 332
  • 449