首页新闻找找看学习计划

.NET Core 控制台程序 Task.WhenAll 中 Task 抛异常问题

0
悬赏园豆:100 [已解决问题] 解决于 2019-05-04 13:44

想在一个 .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);
    }
}
dudu的主页 dudu | 高人七级 | 园豆:40817
提问于:2019-05-04 10:36
< >
分享
最佳答案
1

可以使用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的事件,主动终止执行。

收获园豆:80
天方 | 大侠五级 |园豆:5264 | 2019-05-04 13:19

CancellationTokenSource 是好方法,不需要 throwcts.Cancel() 后异常会被自动抛出

dudu | 园豆:40817 (高人七级) | 2019-05-04 13:43
其他回答(1)
0

一种函数式的解决方案,用下面的函数将 Task.Run 的参数包裹起来

Func<Task> ExitOnException(Func<Task> taskFn)
{
    return async () =>
    {
        try
        {
            await taskFn();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            Environment.Exit(1);
        }
    };
}
收获园豆:20
不如隐茶去 | 园豆:528 (小虾三级) | 2019-05-04 12:35
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册