The async
keyword do cause the CIL to change (even if there's no await inside the method), but it is primarily to allow await
to be present.
But I did not expect the following to happen:
static void Main(string[] args)
{
Task t = Go();
t.Wait();
}
static async Task Go()
{
Console.WriteLine(1);
await AAA(3000);
Console.WriteLine(2);
}
static Task<object> AAA(int a) // <--- No `async`
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Task.Delay(a).ContinueWith(b => tcs.SetResult(null));
return tcs.Task;
}
This print:
1
(wait)
2
But if I change
static Task<object> AAA(int a)
to
static async Task<object> AAA(int a)
It prints:
1
2
(no wait)
Question
Why don't I see the delay? The TCS is only resolved after three seconds. Meanwhile, the task is not resolved and should be awaited.
Without the async
keyword you are returning the TaskCompletionSource
's task from AAA
and so you wait for it to complete (which will happen after the delay completes).
However, when you add the async
keyword , the task returned from the method is the state-machine's task that completes synchronously. That task has inside it (as a result) the TaskCompletionSource
's task but that isn't the task you are waiting on.
If you want that method to wait for the TaskCompletionSource
's task you can await the inner task of Task<Task>
:
await ((Task) await AAA(3000));
Or await the TaskCompletionSource
's instead of returning it:
async Task AAA(int a)
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Task.Delay(a).ContinueWith(b => tcs.SetResult(null));
await tcs.Task;
}
Or even better, just awaiting the Task.Delay
itself:
async Task<object> AAA(int a)
{
await Task.Delay(a);
return null;
}