Cancel child tasks when one of them throws an exception

て烟熏妆下的殇ゞ 提交于 2019-12-12 02:26:45

问题


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;

回答1:


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;
    }


来源:https://stackoverflow.com/questions/22716412/cancel-child-tasks-when-one-of-them-throws-an-exception

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!