Fix cancelation with task start (only for most trivial cases)
authorMarek Safar <marek.safar@gmail.com>
Fri, 7 Oct 2011 16:17:35 +0000 (17:17 +0100)
committerMarek Safar <marek.safar@gmail.com>
Fri, 7 Oct 2011 16:17:35 +0000 (17:17 +0100)
mcs/class/corlib/System.Threading.Tasks/Task.cs
mcs/class/corlib/Test/System.Threading.Tasks/TaskTest.cs

index 36a6887e43d87bdfe8c60d2a0b3d0d6936d3aa0b..7eb4dbedf4e536cfe79dfd685516be323177fd32 100644 (file)
@@ -149,6 +149,10 @@ namespace System.Threading.Tasks
                        // Process taskCreationOptions
                        if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null)
                                parent.AddChild ();
+
+                       if (token.CanBeCanceled) {
+                               token.Register (l => ((Task) l).CancelReal (), this);
+                       }
                }
 
                ~Task ()
index 6bf14ac7a8f7fcc9ae632d9bfb82e410c66d5e07..a6fee0919bdd2d1da5fed3c81395b7d70d23444f 100644 (file)
@@ -89,31 +89,37 @@ namespace MonoTests.System.Threading.Tasks
                                Assert.AreEqual(max, achieved, "#1");
                        });
                }
-               
+
                [Test]
-               public void CancelTestCase()
+               public void CancelBeforeStart ()
                {
-                       CancellationTokenSource src = new CancellationTokenSource ();
-                       
+                       var src = new CancellationTokenSource ();
+
                        Task t = new Task (delegate { }, src.Token);
                        src.Cancel ();
-                       
-                       t.Start ();
-                       Exception ex = null;
-                       
+                       Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
+
                        try {
-                               t.Wait ();
-                       } catch (Exception e) {
-                               ex = e;
+                               t.Start ();
+                               Assert.Fail ("#2");
+                       } catch (InvalidOperationException) {
+                       }
+               }
+
+               [Test]
+               public void CancelBeforeWait ()
+               {
+                       var src = new CancellationTokenSource ();
+
+                       Task t = new Task (delegate { }, src.Token);
+                       src.Cancel ();
+
+                       try {
+                               Assert.IsTrue (t.Wait (1000));
+                               Assert.Fail ();
+                       } catch (AggregateException e) {
+                               Assert.IsInstanceOfType (typeof (TaskCanceledException), e.InnerException);
                        }
-                       
-                       Assert.IsNotNull (ex, "#1");
-                       Assert.IsInstanceOfType (typeof(AggregateException), ex, "#2");
-                       Assert.IsNull (t.Exception, "#3");
-                       
-                       AggregateException aggr = (AggregateException)ex;
-                       Assert.AreEqual (1, aggr.InnerExceptions.Count, "#4");
-                       Assert.IsInstanceOfType (typeof (OperationCanceledException), aggr.InnerExceptions[0], "#5");
                }
 
                [Test, ExpectedException (typeof (InvalidOperationException))]
@@ -149,8 +155,8 @@ namespace MonoTests.System.Threading.Tasks
                                
                                Task t = Task.Factory.StartNew(delegate { });
                                Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
-                               t.Wait();
-                               cont.Wait();
+                               Assert.IsTrue (t.Wait(1000), "#4");
+                               Assert.IsTrue (cont.Wait(1000), "#5");
                                
                                Assert.IsNull(cont.Exception, "#1");
                                Assert.IsNotNull(cont, "#2");
@@ -161,28 +167,32 @@ namespace MonoTests.System.Threading.Tasks
                [Test]
                public void ContinueWithOnAbortedTestCase()
                {
-                       ParallelTestHelper.Repeat (delegate {
-                               bool result = false;
-                               bool taskResult = false;
-                               
-                               CancellationTokenSource src = new CancellationTokenSource ();
-                               Task t = new Task(delegate { taskResult = true; }, src.Token);
-                               src.Cancel ();
-                               
-                               Task cont = t.ContinueWith (delegate { result = true; },
-                                                           TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
+                       bool result = false;
+                       bool taskResult = false;
 
-                               t.Start();
-                               cont.Wait();
-                               
-                               Assert.IsFalse (taskResult, "#-1");
-                               Assert.AreEqual (TaskStatus.Canceled, t.Status, "#0");
-                               Assert.IsTrue (t.IsCanceled, "#0bis");
-                               
-                               Assert.IsNull(cont.Exception, "#1");
-                               Assert.IsNotNull(cont, "#2");
-                               Assert.IsTrue(result, "#3");
-                       });
+                       CancellationTokenSource src = new CancellationTokenSource ();
+                       Task t = new Task (delegate { taskResult = true; }, src.Token);
+
+                       Task cont = t.ContinueWith (delegate { result = true; },
+                                                                               TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
+
+                       src.Cancel ();
+
+                       Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
+
+                       try {
+                               t.Start ();
+                               Assert.Fail ("#2");
+                       } catch (InvalidOperationException) {
+                       }
+
+                       Assert.IsTrue (cont.Wait (1000), "#30");
+
+                       Assert.IsFalse (taskResult, "#3");
+
+                       Assert.IsNull (cont.Exception, "#4");
+                       Assert.IsTrue (result, "#5");
+                       Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
                }
                
                [Test]