2

非同期4層ネストループを実行し、すべての集約例外を出力したいのですが、実行できません。 Parallellibraryで例外を処理する方法に関するMSの投稿をフォローしました

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

ありがとう

4

1 に答える 1

6

counter変数は、スレッドセーフな方法でインクリメントされません。

TPL ループは並行して実行されるため、カウンター変数は複数のスレッドからインクリメントされます。整数変数のインクリメントはアトミックではないため、たとえばロックまたはInterlocked.Incrementを使用して、この部分をスレッドセーフにする必要があります。

throw new Exception(string.Format("number {0} failed on iteration {1}", 
                                  number4, 
                                  Interlocked.Increment(ref counter)));
于 2013-01-13T14:53:27.760 に答える