Reputation: 16264
This is my actual code:
async Task getData()
{
Thread.Sleep(5000);
Console.WriteLine("Step 1");
using (HttpClient api = new HttpClient())
await api.GetAsync("http://google.com/").ContinueWith(
(getTask) =>
Console.WriteLine(getTask.Result.StatusCode);
);
Console.WriteLine("Step 2");
}
private void button1_Click(object sender, EventArgs e)
{
Task<Task> task = new Task<Task>(getData);
task.Start();
task.Wait();
Console.WriteLine("Step 3");
}
I get the following output:
Step 1
Step 3
OK
Step 2
Why does Step 3
not come after Step 2
?
How do I get it to work in sequence, ie to return to the caller of getData
only until everything in getData
is done?
Upvotes: 4
Views: 5190
Reputation: 239824
To try and put things simply and clearly - async Task
(and <T>
) methods are, themselves, responsible for allocating a Task
object which represents their completion.
If you find yourself working with async
methods and allocating Task
objects yourself (either directly, as here, or using static factory methods such as Task.Run
), you've got to recognize that more than one Task
object now exists. You have to be careful and recognize situations where (as here) you create Task
s that themselves now return Task
s.
It's far better, if possible, to embrace async
all the way (as you modify each function to be async
, you'll then tend to locate each call site and make that location async
as well) and to stop allocating any Task
s yourself.
Upvotes: 2
Reputation: 53958
You should also mark you event handler as async
private async Task button1_Click(object sender, EventArgs e)
and await
instead of Wait
:
private async Task button1_Click(object sender, EventArgs e)
{
await getData();
Console.WriteLine("Step 3");
}
When we use the async/await pattern, we should go this way until the first method initiated it. Otherwise, by calling explicitly Wait
or Result
, we may run into deadlock issues. Furthermore, calling explicitly those methods you block the executing thread. So you drop the main benefit of using async/await, which is not blocking the executing thread and run on a separate thread some code and once this is done resume the execution of your code from where you stopped.
Upvotes: 3