From 28b28ac060404030b17a21dd8e5e0154c363703c Mon Sep 17 00:00:00 2001 From: Heejae Chang Date: Tue, 24 Feb 2015 17:22:00 -0800 Subject: [PATCH] make sure we can cancel outside of enumeration --- .../WorkCoordinator.AsyncWorkItemQueue.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncWorkItemQueue.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncWorkItemQueue.cs index 7f92db1748b..da83ee27f28 100644 --- a/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncWorkItemQueue.cs +++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncWorkItemQueue.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Roslyn.Utilities; @@ -104,7 +105,7 @@ public void RequestCancellationOnRunningTasks() lock (_gate) { // request to cancel all running works - _cancellationMap.Do(p => p.Value.Cancel()); + CancelAll_NoLock(); } } @@ -118,8 +119,7 @@ public void Dispose() Dispose_NoLock(); - _cancellationMap.Do(p => p.Value.Cancel()); - _cancellationMap.Clear(); + CancelAll_NoLock(); } } @@ -131,6 +131,24 @@ private bool HasAnyWork_NoLock } } + private void CancelAll_NoLock() + { + // nothing to do + if (_cancellationMap.Count == 0) + { + return; + } + + var cancellations = _cancellationMap.Values.ToList(); + + // it looks like Cancel can cause some code to run at the same thread, which can cause _cancellationMap to be changed. + // make a copy of the list and call cancellation + cancellations.Do(s => s.Cancel()); + + // clear cancellation map + _cancellationMap.Clear(); + } + protected void Cancel_NoLock(object key) { CancellationTokenSource source; -- GitLab