【问题标题】:Why does await not wait?为什么等待不等待?
【发布时间】:2017-07-28 14:31:40
【问题描述】:

这是我的实际代码:

    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 的调用者?

【问题讨论】:

  • 试试task.Result.Wait(),但你的例子似乎有点过于复杂了。
  • 谢谢!!!有用。能解释一下为什么吗?控制流如何设法绕过getData方法的结尾返回给调用者?
  • 看来您真的应该阅读/通过正确介绍 async/await 来工作(例如 this one)。简而言之:getData 已经返回一个任务,通过将其包装在另一个任务中,您必须等待内部任务。或者直接在button1_Click 中写await getData(...)。但要注意,async/await 还有很多内容 - 真的要阅读更多内容。
  • 另外,你应该never use the Task constructor

标签: c# .net async-await task


【解决方案1】:

您还应该将事件处理程序标记为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 的主要好处,它不会阻塞正在执行的线程并在单独的线程上运行一些代码,一旦完成,就会从你停止的地方恢复代码的执行。

【讨论】:

  • 谢谢。我不知道事件处理程序可以是async。这是否意味着所有调用事件处理程序的代码也是async
  • @不客气。这意味着可以异步处理事件而不会阻塞您的应用程序。例如,如果我们为 WPF 应用程序说话,并且单击按钮会触发网络调用,这将需要相当长的时间才能完成,那么如果您的相应处理程序不是异步处理程序,您的 UI 将冻结。
【解决方案2】:

尝试简单明了地说明问题 - async Task(和 &lt;T&gt;)方法本身负责分配一个代表其完成的 Task 对象。

如果您发现自己使用async 方法并且自己分配Task 对象(直接,如这里,或使用静态工厂方法,如Task.Run),你有认识到现在存在多个Task 对象。您必须小心并识别(如此处)您创建 Tasks 的情况,这些情况现在自己返回 Tasks。

如果可能,最好一直采用 async(当您将每个函数修改为 async 时,您将倾向于定位每个呼叫站点并将该位置也设为 async)并停止自己分配任何Tasks。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-12
    • 2022-01-21
    • 2021-05-29
    • 2021-08-02
    • 2020-06-08
    • 1970-01-01
    相关资源
    最近更新 更多