使用任务和 Task.WaitAny 进行异常处理
Exception handling using tasks and Task.WaitAny
Task.WaitAll
方法可以抛出 AggregateException
,但 Task.WaitAny
方法不会。
问题:
- 我不明白框架的开发者这样做的目的是什么?
- 如何使用
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()
等待 任何 一项任务完成(成功或失败)。
当一个人这样做时,除了异常,异常不会传播(抛出)。
WaitAll()
等待 所有 任务完成。
由于它们都抛出异常,因此它们被聚合成一个 AggregateException
.
您可以像这样检查错误:
var tasks = new[] { MyTask22, MyTask23 };
int taskIndex = Task.WaitAny(tasks); //No exceptions
if (taskIndex >= 0)
{
throw tasks[taskIndex].Exception;
}
这里有更多有用的信息:
Task.WaitAny
方法的工作是通知您任务已完成,而不是任务已完成 成功。
我会倒序回答你的问题:
- How to catch an exception from a task using
Task.WaitAny
method?
您可能会问如何抛出 已完成但失败的任务的异常。最简单的方法大概就是Wait
任务:
var tasks = new Task[] { MyTask22, MyTask23 };
int completedTaskIndex = Task.WaitAny(tasks);
tasks[completedTaskIndex].Wait();
- I do not understand for what purpose the developers of the framework did this?
否则该方法将无法完成其预期的工作。您将无法使用此方法来获知任务已完成。您将得到一个无用的 expensive 异常,而不是获得已完成任务的索引。您可以捕获此异常,但您仍然不知道是哪个任务导致了异常。
Task.WaitAll
方法可以抛出 AggregateException
,但 Task.WaitAny
方法不会。
问题:
- 我不明白框架的开发者这样做的目的是什么?
- 如何使用
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()
等待 任何 一项任务完成(成功或失败)。
当一个人这样做时,除了异常,异常不会传播(抛出)。
WaitAll()
等待 所有 任务完成。
由于它们都抛出异常,因此它们被聚合成一个 AggregateException
.
您可以像这样检查错误:
var tasks = new[] { MyTask22, MyTask23 };
int taskIndex = Task.WaitAny(tasks); //No exceptions
if (taskIndex >= 0)
{
throw tasks[taskIndex].Exception;
}
这里有更多有用的信息:
Task.WaitAny
方法的工作是通知您任务已完成,而不是任务已完成 成功。
我会倒序回答你的问题:
- How to catch an exception from a task using
Task.WaitAny
method?
您可能会问如何抛出 已完成但失败的任务的异常。最简单的方法大概就是Wait
任务:
var tasks = new Task[] { MyTask22, MyTask23 };
int completedTaskIndex = Task.WaitAny(tasks);
tasks[completedTaskIndex].Wait();
- I do not understand for what purpose the developers of the framework did this?
否则该方法将无法完成其预期的工作。您将无法使用此方法来获知任务已完成。您将得到一个无用的 expensive 异常,而不是获得已完成任务的索引。您可以捕获此异常,但您仍然不知道是哪个任务导致了异常。