为什么等待不等?

时间:2017-07-28 05:03:18

标签: c# .net async-await task

这是我的实际代码:

    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");
    }

我得到以下输出:

Step 1
Step 3
OK
Step 2

为什么Step 3之后Step 2不会出现?

如何让它按顺序工作,即仅在getData中的所有内容都完成后返回getData的来电者?

2 个答案:

答案 0 :(得分:3)

您还应将事件处理程序标记为async

private async Task button1_Click(object sender, EventArgs e)

await代替Wait

private async Task button1_Click(object sender, EventArgs e)
{
    await getData();

    Console.WriteLine("Step 3");
}

当我们使用async / await模式时,我们应该采用这种方式,直到第一个方法启动它。否则,通过显式调用WaitResult,我们可能会遇到死锁问题。此外,显式调用那些阻止执行线程的方法。所以你放弃使用async / await的主要好处,它不会阻塞正在执行的线程并在一个单独的线程上运行一些代码,一旦完成,就会从你停止的地方恢复执行代码。

答案 1 :(得分:2)

尝试简单明了地表达事物 - async Task(和<T>)方法本身负责分配代表其完成的Task对象。

如果您发现自己使用async方法自行分配Task个对象(可以直接在这里,也可以使用静态工厂方法,例如Task.Run ),您必须认识到现在存在多个Task对象。您必须小心并认识到(在此处)创建Task的情况,现在他们自己返回Task

如果可能的话,最好一直拥抱async(当您将每个功能修改为async时),您将倾向于找到每个呼叫网站并将该位置设为async,并自行停止分配任何Task