Parallel.ForEach和Aggregate异常

时间:2013-01-13 14:12:23

标签: c# task-parallel-library

我想运行异步4层嵌套循环并打印所有聚合异常,但未能这样做。 Followed MS post on how to handle exception in Parallel library

可以得到为什么我总是得到随机数,而它应该打印3 ^ 3次?

Console.WriteLine("{0} was on counter\n\n\n",counter);

class Program
{
    static void Main()
    {
        int counter = 1;

        List<int> numbers = new List<int> {1, 2, 3};

        try
        {
            ConcurrentQueue<Exception> exceptions = new ConcurrentQueue<Exception>();
            Parallel.ForEach(numbers, number1 =>
            {
                Parallel.ForEach(numbers, number2 =>
                {
                    Parallel.ForEach(numbers, number3 =>
                    {
                        Parallel.ForEach(numbers, number4 =>
                        {
                            try
                            {
                                throw new Exception(string.Format("number {0} failed on iteration {1}",number4,counter++));
                            }
                            catch (Exception exception)
                            {
                                exceptions.Enqueue(exception);
                            }

                        });
                    });
                });
            });
            if (!exceptions.IsEmpty)
            {
                throw new AggregateException(exceptions);
            }
        }
        catch (Exception exception)
        {
            Console.WriteLine("{0} was on counter\n\n\n",counter);
            GetInnerException(exception);
        }

        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

    public static void GetInnerException(Exception exception)
    {
        if (exception.GetType().Equals(typeof(AggregateException)))
        {
            AggregateException aggregateException = (AggregateException)exception;
            foreach (Exception innerException in aggregateException.InnerExceptions)
            {
                GetInnerException(innerException);
            }
        }
        else
        {
            Console.WriteLine(exception.ToString());
        }
    }
}

感谢

1 个答案:

答案 0 :(得分:6)

counter变量不以线程安全的方式递增。

由于TPL循环将并行运行,您的计数器变量将从多个线程递增。由于递增整数变量不是原子的,因此您需要将此部分设置为线程安全的,例如使用锁或Interlocked.Increment

throw new Exception(string.Format("number {0} failed on iteration {1}", 
                                  number4, 
                                  Interlocked.Increment(ref counter)));