简体   繁体   中英

Why does await not wait?

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?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM