From 5e58062d5f5b8af0ce2e6b0be0e6a5ddc3613509 Mon Sep 17 00:00:00 2001 From: Danylo Fitel Date: Mon, 20 Apr 2020 17:12:36 -0700 Subject: [PATCH 1/2] Not resetting exception list to null in ReadExceptions, so that in case multiple tasks are finishing at the same time they will both read a non-empty list of exceptions. Returning a copy of exception list from ReadExceptions to prevent concurrent reads by CompleteLoopNow and writes by tasks still running in case the loop was canceled. --- src/Extensions/ParallelForEachExtensions.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Extensions/ParallelForEachExtensions.cs b/src/Extensions/ParallelForEachExtensions.cs index 4c7d7f8..68ce8fd 100644 --- a/src/Extensions/ParallelForEachExtensions.cs +++ b/src/Extensions/ParallelForEachExtensions.cs @@ -76,11 +76,12 @@ public List ReadExceptions() _exceptionListLock.Enter(ref lockTaken); try { - return _exceptionList; + // Return a copy, so the list being returned will not be modified + // by tasks that are still running if the loop was canceled + return new List(_exceptionList); } finally { - _exceptionList = null; _exceptionListLock.Exit(useMemoryBarrier: false); } } From 4becfd4dd3fa0cb24027482d8f0207bf9f3cf9b6 Mon Sep 17 00:00:00 2001 From: Danylo Fitel Date: Mon, 17 Aug 2020 17:54:01 -0700 Subject: [PATCH 2/2] Fixing the happy path --- src/Extensions/ParallelForEachExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Extensions/ParallelForEachExtensions.cs b/src/Extensions/ParallelForEachExtensions.cs index 68ce8fd..fa20ccf 100644 --- a/src/Extensions/ParallelForEachExtensions.cs +++ b/src/Extensions/ParallelForEachExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -78,7 +79,7 @@ public List ReadExceptions() { // Return a copy, so the list being returned will not be modified // by tasks that are still running if the loop was canceled - return new List(_exceptionList); + return new List(_exceptionList ?? Enumerable.Empty()); } finally {