你能解释为什么,如果我不等待一个异步任务异常没有被捕获?(Can you explain why t

2019-09-17 18:51发布

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

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中通知我,我不会等待的方法的警告消息。 然而该解决方案编译和我很害怕这会在我的代码在其他地方发生,如果我用大量的异步/ AWAIT。 所以,可以请你说明理由,并peraphs给一些金科玉律避免呢?

PS:它的工作原理,如果在代码button1_Click我写的:

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

Answer 1:

在你第一次button1_Click实现,你忽略了的结果Task的返回TestWork

在修改后的版本,在await检查的异常和propogates为你捕捉。

事实上,你所看到的编译器警告通常是很重要的。 如果TestWork居然跑在不同的线程的东西,那么因为包装Task在你第一次执行不等待TestWork完成,它只是尽快完成自身TestWork已经开始。

写这种方式使得它更清晰:

Task task = Task.Run( () =>
    {
        Task t = TestWork();
        // ignore t
    }
);


文章来源: Can you explain why the exception is not caught if I do not await an async task?