您能解释一下为什么我不等待异步任务时没有捕获到异常吗? [英] Can you explain why the exception is not caught if I do not await an async task?

查看:131
本文介绍了您能解释一下为什么我不等待异步任务时没有捕获到异常吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Starting from an issue I had on my code, I've created this simple app to recreate the problem:

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,这可能会在代码中的其他地方发生。

The code for button1_Click will not catch the exception. I've verified that this is because I'm not awaiting the TestWork async method. Indeed I've a warning message from Visual Studio that inform me I'm not awaiting the method. However the solution compile and I'm scared this can happen somewhere else in my code if I use extensively the async/await. So can you please explain the reason and peraphs give some golden rule to avoid it?

PS:如果在 button1_Click的代码中有效,那么您可以解释一下原因吗? code>我这样写:

P.S.: It works if in the code for button1_Click I write:

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


推荐答案

在您的第一个 button1_Click 实现,您将忽略 TestWork 返回的任务的结果。

In your first button1_Click implementation, you are ignoring the result of the Task returned by TestWork.

在修改后的版本中,等待检查异常并将其传播给您捕获。

In your modified version, the await checks for an Exception and propogates it for you to catch.

实际上,您看到的编译器警告通常很重要。如果 TestWork 实际上在另一个线程上运行了某些内容,则因为第一个实现中的包装器 Task 不会等待 TestWork 完成,它会在 TestWork 开始后立即完成。

In fact, the compiler warning you are seeing is normally important. If TestWork actually ran something on a different thread, then because the wrapper Task in your first implementation doesn't wait for TestWork to complete, it would just complete itself as soon as TestWork had started.

这样写可以使内容更清晰:

Writing it this way makes it clearer:

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

这篇关于您能解释一下为什么我不等待异步任务时没有捕获到异常吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆