即使抛出异常,也要执行所有任务
本文关键字:执行 任务 抛出异常 | 更新日期: 2023-09-27 18:10:22
我得到了以下方法:
public async Task PublishAsync<TApplicationEvent>(TApplicationEvent e)
where TApplicationEvent : ApplicationEvent
{
using (var scope = _container.CreateScope())
{
var implementations = scope.ResolveAll<IApplicationEventSubscriber<TApplicationEvent>>();
var tasks = implementations.Select(x => x.HandleAsync(e));
try
{
await Task.WhenAll(tasks);
EventPublished(this, new EventPublishedEventArgs(scope, e, true));
}
catch
{
EventPublished(this, new EventPublishedEventArgs(scope, e, false));
throw;
}
}
}
我认为所有的任务都应该在抛出异常之前执行,但是当第一个任务抛出异常时,方法似乎就会终止。
我是否可以配置WhenAll
执行所有任务并在返回前生成所有失败的AggregateException ?
这正是WhenAll
所做的。然而,当你await
一个任务,抛出一个聚合异常,其中有多个异常,它将重新抛出只是第一个异常在聚合异常,而不是重新抛出聚合异常本身。(这是因为抛出异常的绝大多数任务在聚合中永远不会有多个表达式,所以取消异常包装几乎总是期望的行为。)
在await
之前保持对Task
的引用,以便以后可以访问聚合异常,或者干脆不await
WhenAll
的结果,而是使用手动延续。
task . whenall() ->创建一个任务,该任务将在所有提供的任务完成时完成。
无论单个任务中发生了什么,它都将完成所有任务的执行。
在给定的任务集合中,一个任务中的异常不会阻止其他任务的执行。
var tasks = new List<Task>();
Task t1 = Task.Run(() =>
{
throw new Exception("test1");
});
tasks.Add(t1);
Task t2 = Task.Run(() =>
{
throw new Exception("test2");
});
tasks.Add(t2);
Task t3 = Task.Run(() =>
{
Console.WriteLine("Pseudo Work");
});
tasks.Add(t3);
try
{
await Task.WhenAll(tasks);
}
catch (Exception ex)
{
// Only t1 & t2 will qualify and t3 will be successful (Pseudo Work will be printed on console)
var exceptions = tasks.Where(t => t.Exception != null).Select(t => t.Exception);
}
如果我运行以下示例,所有任务都完成了,但它仍然抛出,我认为这是预期的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaskWhenAllTest
{
class Program
{
static void Main(string[] args)
{
try
{
Task task = Test();
Task.WaitAll(new Task[] { task });
Console.WriteLine(task.Status);
}
catch (Exception)
{
//Console.WriteLine(ex.ToString());
Console.WriteLine("Task errored.");
}
Console.WriteLine("Done.");
Console.ReadKey();
}
static async Task Test()
{
var task1 = Task.Factory.StartNew(() => { System.Threading.Thread.Sleep(1000); throw new Exception("Test1 exception"); });
var task2 = Task.Factory.StartNew(() => { System.Threading.Thread.Sleep(500); Console.WriteLine("Task 2 complete."); });
var task3 = Task.Factory.StartNew(() => { System.Threading.Thread.Sleep(250); Console.WriteLine("Task 3 complete."); });
await Task.WhenAll(new Task[] {task1, task2, task3 });
}
}
}