Is there an easy way to step through a parallel.foreach? What is the best way to debug this with a break point?
-
2if you don't care to debug parallelism, and just want to check what is happening inside the loop, copy it to a serial foreach and step through it (commenting out the parallel for production) – Dimitri Jun 19 '12 at 20:39
-
@Dimitri Safer/simpler to just make `Parallel.ForEach` run sequentially for debugging. – Reed Copsey Jun 19 '12 at 20:45
-
@Reed - yep that's why i upvoted your answer. Never thought of it before – Dimitri Jun 19 '12 at 21:30
8 Answers
During debug, I'll often setup my Parallel.ForEach
to run with MaxDegreeOfParallelism
set to 1. This makes it far simpler to debug.
const bool forceNonParallel = true;
var options = new ParallelOptions { MaxDegreeOfParallelism = forceNonParallel ? 1 : -1 };
Parallel.ForEach(collection, options, item =>
{ //...
However, this will not help with debugging issues relating to race conditions or data synchronization, and will in fact often hide or eliminate real problems in your code.
Those issues can often be debugged much more easily by using the new tools in VS 2010, such as the Parallel Tasks window, or by using the various techniques listed in Debugging Multithreaded Applications, such as switching threads, locking threads while stepping, etc.

- 554,122
- 78
- 1,158
- 1,373
-
Do you know of any documentation for "-1" ? The msdn article says that an error will be thrown if it is set to 0 or any value below -1, but doesn't explain the -1. – granadaCoder Apr 28 '15 at 18:44
-
@granadaCoder See https://msdn.microsoft.com/en-us/library/system.threading.tasks.paralleloptions.maxdegreeofparallelism%28v=vs.110%29.aspx "If it is -1, there is no limit on the number of concurrently running operations." – Reed Copsey Apr 28 '15 at 19:22
Similar to other answers here, we set degree of parallelism to 1 when debugging, but we do this with an extension method, like:
public static ParallelQuery<TSource> AsDebugFriendlyParallel<TSource>(this IEnumerable<TSource> source)
{
var pQuery = source.AsParallel();
#if DEBUG
pQuery = pQuery.WithDegreeOfParallelism(1);
#endif
return pQuery;
}
Then, instead of using .AsParallel()
we use .AsDebugFriendlyParallel()

- 13,871
- 9
- 56
- 78
-
1Please note that `Parallel.ForEach()` and `IEnumerable
.AsParallel()` are not quite the same - [https://stackoverflow.com/questions/3789998/parallel-foreach-vs-foreachienumerablet-asparallel](https://stackoverflow.com/questions/3789998/parallel-foreach-vs-foreachienumerablet-asparallel) – sventevit Feb 03 '20 at 08:45
You can actually get similar results with Visual Studio just by freezing all the threads except one, select all threads but one in the Threads windows and right click -> Freeze like this:
Also, if you want to reproduce a race condition and stopping on breakpoints breaks it, you can always add tracepoints - either with visual studio or with plugins that help with it, such as Oz Code

- 656
- 4
- 8
As @PaulG answered i think best practice is just set MaxDegreeOfParallelism
value to 1
. Then normally Parallel
also will work similar to regular loop like For
, Foreach
. This is the faster way to debug on Parallel
. So you don't need to switch code between regular loop and Parallel
.
Parallel.For(0, itemsList.Count, new ParallelOptions { MaxDegreeOfParallelism = 1 }, i =>
{
//your process goes here
}

- 1,288
- 1
- 13
- 24
Temporarily rewrite it as a non-parallel foreach, or use preprocessor directives to execute non-parallel code when running in debug mode.

- 2,375
- 2
- 18
- 26
I like to use the "When Hit" option on a breakpoint (right-click the breakpoint, select "When Hit...". You can print a message to the console that includes values of variables, the thread you are on, etc.

- 13,259
- 5
- 46
- 45
OzCode will help you a lot, it has a feature like tracepoints on steroids that is super useful when debuging concurrent\parallel code https://www.youtube.com/watch?v=_vuMi-3jGwY

- 194
- 7
This is the strategy I use which makes every Loop go sequential when in debug mode
var parOpts = new ParallelOptions { MaxDegreeOfParallelism = -1 }; //No limit to parallel degree
#if DEBUG
parOpts.MaxDegreeOfParallelism = 1; //Set parallel to 1
#endif
Parallel.ForEach(links, node =>
{
string url = node.Attributes["href"].Value;
Link link = ParseLink(url);
link.LinkText = node.InnerText;
if (link.Domain == RootLink.Domain)
{
if (link.Page == RootLink.Page)
link.Type = LinkType.Section;
else
link.Type = LinkType.Internal;
}
else
link.Type = LinkType.External;
linksList.Add(link);
});

- 13,505
- 11
- 64
- 87