I have probably worked myself into a rather immature confusion. Please refer the code below (console app)
namespace Tasks101
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
var x = p.Blah();
}
private async Task Blah()
{
await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
}
private async void ReturnsVoid()
{
await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
}
private void Nothing()
{
}
}
}
My question is that in Blah()
method I don't have any explicit return statement yet when this executes
var x = p.Blah();
the type of x
is Task
. Again I have no return statement in ReturnsVoid
method but that compiles too.
So the questions are
- What is returning a
Task
from theBlah
method without my having areturn
statement there and why is that same thing not returning anything fromReturnsVoid
method. - How do I control what gets returned from the
Blah
method? What if I had two await statements there one after the other?
The
async
keyword transforms the method and constructs the returnedTask
instance. There is nothing returned from theasync void
method because it returnsvoid
; this lack of aTask
is one reason why you should avoidasync void
.async void
is not a natural asynchronous method signature; it is only supported so that event handlers may beasync
.If you want to return a value, then you should have the method return a
Task<T>
, e.g.,Task<int> BlahAsync()
, and then you can just return the value directly, e.g.,return 13;
The number ofawait
s in the method has nothing to do with it. When the method executes the actual return (e.g.,return 13
), theasync
keyword interprets that as completing theTask<int>
that was already constructed.I have an
async
intro on my blog that you may find helpful.Task
for you that represents the entire asynchronous operation.async void
- This should be avoided in all cases other than event handlersasync Task
- Here you have no control of the returned task, and it will be completed when the whole operation has ended (or when an exception is thrown) no matter how many awaits you have in it.async Task<T>
- This allows to actually return a value but behaves just the same asasync Task
.