Tuesday, February 22, 2011

C#: Parallel ForEach AggregateException

When working with Parallel.ForEach, you'll at some point want to handle exceptions cleanly.  I found that the AggregateException class to be very helpful.  Check out the following example to see how it works:



private static void AggregateExceptionDemo()
        {
            byte[] myData = new byte[500];
            Random r = new Random();
            r.NextBytes(myData);

            try
            {
                DoWorkInParallel(myData);
            }
            catch (AggregateException ae)
            {
                foreach (var ex in ae.InnerExceptions)
                {
                    if (ex is ArgumentException)
                        Console.WriteLine(ex.Message);
                    else
                        throw ex;
                }
            }
        }



        private static void DoWorkInParallel(byte[] myData)
        {
            // Use ConcurrentQueue to enable safe enqueueing from multiple threads.
            var exceptions = new ConcurrentQueue();

            // Execute the complete loop and capture all exceptions.
            Parallel.ForEach(myData, d =>
            {
                try
                {
                    // Cause a few exceptions, but not too many.
                    if (d < 0x3)
                        throw new ArgumentException(String.Format("value is {0:x}. Elements must be greater than 0x3.", d));
                    else
                        Console.Write(d + " ");
                }
                // Store the exception and continue with the loop.                    
                catch (Exception e) { exceptions.Enqueue(e); }
            });

            // Throw the exceptions here after the loop completes.
            if (exceptions.Count < 0) throw new AggregateException(exceptions);
        }

2 comments: