[System.Core] Check for canceled operation when invoking inner call
authorJérémie Laval <jeremie.laval@gmail.com>
Wed, 12 Sep 2012 13:48:34 +0000 (15:48 +0200)
committerJérémie Laval <jeremie.laval@gmail.com>
Wed, 12 Sep 2012 13:49:07 +0000 (15:49 +0200)
mcs/class/System.Core/System.Linq.Parallel/ParallelExecuter.cs

index 262e8d112ea0aba9bdafd2616b5794dd1388f1fb..96a5fe1f8e3f7d10c24b84cda5d57a66d17c14d6 100644 (file)
@@ -105,13 +105,18 @@ namespace System.Linq.Parallel
                                tasks[i] = Task.Factory.StartNew (() => {
                                        try {
                                                foreach (TElement item in enumerables[index]) {
-                                                       // This is from specific operators
-                                                       if (options.ImplementerToken.IsCancellationRequested)
+                                                       if (!CheckTokens (options))
                                                                break;
-                                                       if (options.Token.IsCancellationRequested)
-                                                               throw new OperationCanceledException (options.Token);
 
-                                                       call (item, src.Token);
+                                                       try {
+                                                               call (item, src.Token);
+                                                       } catch (OperationCanceledException canceledException) {
+                                                               if (canceledException.CancellationToken != src.Token)
+                                                                       throw canceledException;
+                                                       }
+
+                                                       if (!CheckTokens (options))
+                                                               break;
                                                }
                                        } finally {
                                                if (endAction != null)
@@ -123,6 +128,16 @@ namespace System.Linq.Parallel
                        return tasks;
                }
 
+               static bool CheckTokens (QueryOptions options)
+               {
+                       // This is from specific operators
+                       if (options.ImplementerToken.IsCancellationRequested)
+                               return false;
+                       if (options.Token.IsCancellationRequested)
+                               throw new OperationCanceledException (options.Token);
+                       return true;
+               }
+
                internal static void ProcessAndBlock<T> (QueryBaseNode<T> node, Action<T, CancellationToken> call)
                {
                        QueryOptions options = CheckQuery (node, true);