简体   繁体   English

有没有办法在任务不冻结 UI 的情况下处理任务引发的异常?

[英]Is there a way to handle exceptions thrown by a task without the task freezing the UI?

public async void CallTask()
{
    try
    {
        await Task.Run(MyTaskMethod);
    }
    catch (ArgumentException ex) // Exception doesn't get handled
    {
        MessageBox.Show(ex.Message);
    }
}

public Task MyTaskMethod()
{
    throw new ArgumentException("This is an error message"); 
}

My task throws an exception I want to capture in a higher level.我的任务引发了我想在更高级别捕获的异常。

How can I handle the exception being thrown on MyTaskMethod without freezing the UI?如何在不冻结 UI 的情况下处理 MyTaskMethod 上引发的异常?

Two options:两种选择:

  1. Catch the exception in MyTaskMethodMyTaskMethod中捕获异常
  2. Catch AggregateException that is thrown by the Task捕获 Task 抛出的 AggregateException

I believe 1 is fairly straight forwards to understand.我相信 1 是相当直截了当的理解。

Number 2 looks like this: 2号看起来像这样:

public async void CallTask()
{
    try
    {
        await Task.Run(MyTaskMethod);
    }
    catch (AggregateException ex) // Exception doesn't get handled
    {
        MessageBox.Show(ex.InnerExceptions[0].Message);
    }
}

public Task MyTaskMethod()
{
    throw new ArgumentException("This is an error message"); 
}

This is necessary because when an exception is thrown on a Task it gets wrapped in an AggregateException before being returned.这是必要的,因为当在 Task 上引发异常时,它会在返回之前被包装在 AggregateException 中。 This means trying to catch the inner exception will fail, so we need to first catch the AggregateException and then unwrap.这意味着试图捕获内部异常会失败,所以我们需要先捕获 AggregateException 然后再展开。

You can't if you use a message box: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.messagebox?view=net-5.0如果您使用消息框,则不能: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms0.message?

Displays a message window, also known as a dialog box, which presents a message to the user.显示消息 window,也称为对话框,向用户显示消息。 It is a modal window, blocking other actions in the application until the user closes it.它是一个模态 window,阻止应用程序中的其他操作,直到用户关闭它。

You can use inline labels in your form and set the text property and show then only on error.您可以在表单中使用内联标签并设置 text 属性,然后仅在出错时显示。

If your problem is that your exception is not handled, then catch the AggregateException https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/exception-handling-task-parallel-library如果您的问题是未处理您的异常,请捕获AggregateException https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/exception-handling-task-parallel-library

To propagate all the exceptions back to the calling thread, the Task infrastructure wraps them in an AggregateException instance.要将所有异常传播回调用线程,Task 基础结构将它们包装在 AggregateException 实例中。 The AggregateException exception has an InnerExceptions property that can be enumerated to examine all the original exceptions that were thrown AggregateException 异常有一个 InnerExceptions 属性,可以枚举该属性以检查引发的所有原始异常

public async void CallTask()
{
    try
    {
        await Task.Run(MyTaskMethod);
    }
    catch (AggregateException ex) // Exception does get handled
    {
        // access inner exceptions here. 
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM