简体   繁体   English

使用任务和 Task.WaitAny 处理异常

[英]Exception handling using tasks and Task.WaitAny

Task.WaitAll method can throw an AggregateException , but Task.WaitAny method does not. Task.WaitAll方法可以抛出AggregateException ,但Task.WaitAny方法不会。

Questions:问题:

  1. I do not understand for what purpose the developers of the framework did this?我不明白框架的开发人员这样做的目的是什么?
  2. How to catch an exception from a task using Task.WaitAny method?如何使用Task.WaitAny方法从任务中捕获异常?

Example:例子:

using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            void MyMethodForDivideByZeroException()
            {
                int a = 1;
                a = a / 0;
            }

            void MyMethodForIndexOutOfRangeException()
            {
                int[] MyArrayForInt = new int[2] { 1, 2 };
                Console.WriteLine(MyArrayForInt[2]);
            }

            Task MyTask22 = new Task(MyMethodForDivideByZeroException);
            Task MyTask23 = new Task(MyMethodForIndexOutOfRangeException);

            MyTask22.Start();
            MyTask23.Start();

            Task.WaitAny(MyTask22, MyTask23); //No exceptions
            //Task.WaitAll(MyTask22, MyTask23); //AggregateException

            Console.WriteLine(MyTask22.Status);
            Console.WriteLine(MyTask23.Status);
        }
    }
}

WaitAny() waits for any one of the tasks to complete (successfuly or otherwise). WaitAny()等待任何一项任务完成(成功与否)。
When one does, with an exception, the exception is not propagated (thrown).当有异常时,异常不会传播(抛出)。

WaitAll() waits for all of the tasks to complete. WaitAll()等待所有任务完成。
As they both throw an exception, these are aggregated into an AggregateException .由于它们都抛出异常,因此它们被聚合到AggregateException中。

You can check for errors like this:您可以检查以下错误:

var tasks = new[] { MyTask22, MyTask23 };
int taskIndex = Task.WaitAny(tasks); //No exceptions
        
if (taskIndex >= 0)
{
    throw tasks[taskIndex].Exception;
}

More useful information here:更多有用的信息在这里:

The job of the Task.WaitAny method is to inform you that a task has completed, not that a task has completed successfully . Task.WaitAny方法的工作是通知您任务已完成,而不是任务已成功完成。

I'll answer your questions in reverse order:我将按相反的顺序回答您的问题:

  1. How to catch an exception from a task using Task.WaitAny method?如何使用Task.WaitAny方法从任务中捕获异常?

You probably ask how to throw the exception of a completed task that has failed.您可能会问如何抛出已完成任务失败的异常。 The simplest way is probably just to Wait the task:最简单的方法可能就是Wait任务:

var tasks = new Task[] { MyTask22, MyTask23 };
int completedTaskIndex = Task.WaitAny(tasks);
tasks[completedTaskIndex].Wait();
  1. I do not understand for what purpose the developers of the framework did this?我不明白框架的开发人员这样做的目的是什么?

Because otherwise the method would not be able to do its intended job.因为否则该方法将无法完成其预期的工作。 You won't be able to use this method in order to be informed about the completion of a task.您将无法使用此方法来了解任务的完成情况。 Instead of getting the index of the completed task, you would get a useless and expensive exception.您将获得一个无用且昂贵的异常,而不是获取已完成任务的索引。 You could catch this exception, but you would still don't know which of the tasks is the one that caused the exception.您可以捕获此异常,但您仍然不知道哪个任务是导致异常的任务。

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

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