3

从我在代码中遇到的问题开始,我创建了这个简单的应用程序来重现问题:

private async void button1_Click(object sender, EventArgs e)
{
    Task task = Task.Run(() =>
    {
        TestWork();
    });
    try
    {
        await task;
        MessageBox.Show("Exception uncaught!");
    }
    catch (Exception) { MessageBox.Show("Exception caught!"); }
}

private async void button2_Click(object sender, EventArgs e)
{
    Task task = TestWork();
    try
    {
        await task;
        MessageBox.Show("Exception uncaught!");
    }
    catch (Exception) { MessageBox.Show("Exception caught!"); }
}

private async Task TestWork()
{
    throw new Exception();
}

的代码button1_Click不会捕获异常。我已经验证这是因为我没有等待TestWork异步方法。事实上,我收到了来自 Visual Studio 的警告消息,通知我我没有等待该方法。但是,解决方案可以编译,如果我广泛使用 async/await,我担心这会发生在我的代码中的其他地方。那么,您能否解释一下原因,并给出一些避免它的黄金法则?

PS:如果在button1_Click我写的代码中它可以工作:

Task task = Task.Run(async () =>
{
    await TestWork();
});
4

1 回答 1

2

在您的第一个button1_Click实现中,您忽略了Taskby 返回的结果TestWork

在您的修改版本中,await检查异常并传播它以供您捕获。

事实上,您看到的编译器警告通常很重要。如果TestWork实际上在不同的线程上运行了某些东西,那么因为Task您的第一个实现中的包装器不会等待TestWork完成,它会TestWork在启动后立即完成。

这样写会更清楚:

Task task = Task.Run( () =>
    {
        Task t = TestWork();
        // ignore t
    }
);
于 2012-06-05T10:25:42.073 回答