想在一个 .NET Core 控制台程序中实现当 Task.WhenAll 中任何一个 Task 抛异常时立即让控制台程序退出,请问如何实现?
比如下面的代码,即使在一个任务中抛了异常,其他任务也会正常运行
class Program
{
static async Task Main(string[] args)
{
var tasks = Enumerable.Range(0, 1000).Select(i =>
Task.Run(async () =>
{
Console.WriteLine($"Task {i} is running");
if (i == 5) throw new Exception($"Exit at {i}");
await Task.Delay(100);
}));
await Task.WhenAll(tasks);
}
}
可以使用CancellationToken,就本例使用Task.Run的方式下,可以这么改:
var cts = new CancellationTokenSource();
var tasks = Enumerable.Range(0, 100).Select(i =>
Task.Run(async () =>
{
try
{
Console.WriteLine($"Task {i} is running");
if (i == 5) throw new Exception($"Exit at {i}");
await Task.Delay(100);
}
catch
{
cts.Cancel();
throw;
}
}, cts.Token));
当某个task抛异常后, Task.run就不会接着调用其他的任务了。如果是其它方式,参考下Task.Run的实现就可以了。
已经调度了的任务无法终止,可以自己通过检测CancellationToken的状态或者注册CancellationToken的事件,主动终止执行。
CancellationTokenSource
是好方法,不需要 throw
,cts.Cancel()
后异常会被自动抛出
一种函数式的解决方案,用下面的函数将 Task.Run 的参数包裹起来
Func<Task> ExitOnException(Func<Task> taskFn)
{
return async () =>
{
try
{
await taskFn();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Environment.Exit(1);
}
};
}