当子任务之一引发异常时,取消子任务 [英] Cancel child tasks when one of them throws an exception

查看:156
本文介绍了当子任务之一引发异常时,取消子任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想改进以下代码以添加取消支持.基本上,一旦孩子抛出异常,我需要取消所有孩子以及父任务.我写了下面的代码作为学习经验.我只能在所有孩子都完成后才能看到AggregateException,但是我不希望那样.

I'd like to improve the following code to add cancellation support. Basically, what I need to do is cancel all children as well as the parent task once a child throws an exception. I wrote the below code as a learning experience. I can see AggregateException only after all children finish, but I don't want that.

    static int GetSum()
    {
        var parent = Task<int>.Factory.StartNew(() =>
        {
            var children = new Task<int>[100];
            for (var i = 0; i < children.Length; i++)
            {
                var index = i;
                children[index] = Task<int>.Factory.StartNew(() =>
                {
                    var randomNumber = new Random().Next(5);
                    if (randomNumber == 0)
                    {
                        throw new Exception();
                    }

                    return randomNumber;
                }, TaskCreationOptions.AttachedToParent);
            }

            Task.WaitAll();
            Console.WriteLine("Children finished");
            return children.Sum(t => t.Result);
        });

        parent.Wait();
        Console.WriteLine("Parent finished");
        return parent.Result;
    }

我不知道如何使用以下内容:

I believe I need to use the following though I don't know how:

var source = new CancellationTokenSource();
var token = source.Token;

推荐答案

您可以只使用

you can just use Task.WaitAny instead of WaitAll and make a cancel request to the token once an AgregateException was thrown something like this

static int GetSum()
    {
        var tokenSource = new CancellationTokenSource();
        var token = tokenSource.Token;
        var parent = Task<int>.Factory.StartNew(() =>
        {
            var children = new Task<int>[100];
            for (var i = 0; i < children.Length; i++)
            {
                var index = i;
                children[index] = Task<int>.Factory.StartNew(() =>
                {
                    for (int j = 0; j < 100000; j++)
                    {


                    if (!token.IsCancellationRequested)
                    {


                        var randomNumber = new Random().Next(5);
                        if (randomNumber == 0)
                        {
                            throw new Exception();
                        }

                        return randomNumber;
                    }
                    else
                    {
                        token.ThrowIfCancellationRequested();
                    }
                    }
                    return 0;
                }
                , token);
            }
            try
            {
                Task.WaitAny(children);
            }
            catch (AggregateException ae)
            {
                tokenSource.Cancel();
                ae.Handle((task) =>
                    {
                        Console.WriteLine("Cancel all others child tasks  requested ");
                        return true;
                    });
            }

            Console.WriteLine("Children finished");
            return children.Sum(t => t.Result);
        });

        try
        {
            parent.Wait();
        }
        catch (AggregateException aex)
        {
            aex.Handle((task) =>
            {
                Console.WriteLine("Cancel child work  done ");
                return true;
            });              
        }

        Console.WriteLine("Parent finished");
        return parent.Result;
    }

这篇关于当子任务之一引发异常时,取消子任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆