3

I have some code I'm going to parallelize. It currently looks something like this:

foreach (var item in collection) { if (error) { throw new Exception(); } } 

The exception and its stack trace are saved in a log file.

After parallelization, it would look like this:

Parallel.ForEach(collection, item => { if (error) { throw new Exception(); } }); 
  1. How will this exception stop the parallel execution of the other items? Is there a way to stop all other executions once an error is encountered in one the loop threads?
  2. How will this influence the exception stack trace?

2 Answers 2

2
  1. When an exception is thrown, execution of the items that have not yet been scheduled will be cancelled. Items that are already scheduled, however, will not and cannot be cancelled. (Remember, this happens in parallel, which is why you use Parallel in the first place.) They will run to the end, and may themselves throw exceptions.

  2. Because of this, there might be multiple exceptions thrown in a parallel loop. That is why they are always wrapped in an AggregateException, even when an exception was thown only once. You can catch that AggregateException and enumerate through its InnerExceptions property, which contains all exceptions thrown, together with their stack traces:


try { Parallel.ForEach(collection, item => { if (error) { throw new Exception(); } }); } catch (AggregateException ex) { foreach (var exception in ex.InnerExceptions) { // do something } } 
Sign up to request clarification or add additional context in comments.

Comments

0

The following code can be used to verify the behavior discussed in the first part of Evk's answer:

 static void TryCatchFunction() { ConcurrentBag<string> bag = null; int numItemsInBag = 0; try { ErrorFunction(out bag); numItemsInBag = bag.Count; } catch (Exception) { numItemsInBag = bag.Count; } } static void ErrorFunction(out ConcurrentBag<string> bag) { string[] strings = new string[] { "1", "2", "3", "4", "5", "6" }; ConcurrentBag<string> inFunctionBag = new ConcurrentBag<string>(); bag = inFunctionBag; Parallel.ForEach(strings, (str, state) => { if (str == "2" || str == "4") { inFunctionBag.Add(str); throw new Exception(); } }); } 

The number of items in the bag varies between method calls on a dual core machine. This occurs because sometimes the Exception cancels execution of the other thread and other times both run until completion.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.