5 // Marek Safar <marek.safar@gmail.com>
7 // Copyright (c) 2008 Jérémie "Garuma" Laval
8 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33 using System.Threading;
34 using System.Threading.Tasks;
35 using System.Collections.Generic;
36 using NUnit.Framework;
39 using NUnit.Framework.SyntaxHelpers;
42 namespace MonoTests.System.Threading.Tasks
45 public class TaskTests
47 class MockScheduler : TaskScheduler
49 public event Action<Task, bool> TryExecuteTaskInlineHandler;
51 protected override IEnumerable<Task> GetScheduledTasks ()
53 throw new NotImplementedException ();
56 protected override void QueueTask (Task task)
61 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
63 if (TryExecuteTaskInlineHandler != null)
64 TryExecuteTaskInlineHandler (task, taskWasPreviouslyQueued);
66 return base.TryExecuteTask (task);
77 tasks = new Task[max];
80 void InitWithDelegate(Action action)
82 for (int i = 0; i < max; i++) {
83 tasks[i] = Task.Factory.StartNew(action);
88 public void WaitAnyTest()
90 ParallelTestHelper.Repeat (delegate {
94 InitWithDelegate(delegate {
95 int times = Interlocked.Exchange (ref flag, 1);
97 SpinWait sw = new SpinWait ();
98 while (finished == 0) sw.SpinOnce ();
100 Interlocked.Increment (ref finished);
104 int index = Task.WaitAny(tasks, 1000);
106 Assert.AreNotEqual (-1, index, "#3");
107 Assert.AreEqual (1, flag, "#1");
108 Assert.AreEqual (1, finished, "#2");
113 public void WaitAny_Empty ()
115 Assert.AreEqual (-1, Task.WaitAny (new Task[0]));
119 public void WaitAny_Zero ()
121 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { })}, 0), "#1");
122 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { }) }, 20), "#1");
126 public void WaitAny_Cancelled ()
128 var cancelation = new CancellationTokenSource ();
129 var tasks = new Task[] {
130 new Task (delegate { }),
131 new Task (delegate { }, cancelation.Token)
134 cancelation.Cancel ();
136 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
137 Assert.IsTrue (tasks[1].IsCompleted, "#2");
138 Assert.IsTrue (tasks[1].IsCanceled, "#3");
142 public void WaitAny_CancelledWithoutExecution ()
144 var cancelation = new CancellationTokenSource ();
145 var tasks = new Task[] {
146 new Task (delegate { }),
147 new Task (delegate { })
151 var mre = new ManualResetEventSlim (false);
152 ThreadPool.QueueUserWorkItem (delegate {
153 res = Task.WaitAny (tasks, 20);
157 cancelation.Cancel ();
158 Assert.IsTrue (mre.Wait (1000), "#1");
159 Assert.AreEqual (-1, res);
163 public void WaitAny_OneException ()
165 var mre = new ManualResetEventSlim (false);
166 var tasks = new Task[] {
167 Task.Factory.StartNew (delegate { mre.Wait (1000); }),
168 Task.Factory.StartNew (delegate { throw new ApplicationException (); })
171 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
172 Assert.IsFalse (tasks[0].IsCompleted, "#2");
173 Assert.IsTrue (tasks[1].IsFaulted, "#3");
179 public void WaitAny_SingleCanceled ()
181 var src = new CancellationTokenSource ();
182 var t = Task.Factory.StartNew (() => { Thread.Sleep (200); src.Cancel (); src.Token.ThrowIfCancellationRequested (); }, src.Token);
183 Assert.AreEqual (0, Task.WaitAny (new [] { t }));
186 public void WaitAny_ManyExceptions ()
188 CountdownEvent cde = new CountdownEvent (3);
190 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
191 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
192 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
195 Assert.IsTrue (cde.Wait (1000), "#1");
198 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#2");
199 } catch (AggregateException e) {
200 Assert.AreEqual (3, e.InnerExceptions.Count, "#3");
205 public void WaitAny_ManyCanceled ()
207 var cancellation = new CancellationToken (true);
209 Task.Factory.StartNew (delegate { }, cancellation),
210 Task.Factory.StartNew (delegate { }, cancellation),
211 Task.Factory.StartNew (delegate { }, cancellation)
215 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#1");
216 } catch (AggregateException e) {
217 Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
222 public void WaitAllTest ()
224 ParallelTestHelper.Repeat (delegate {
226 InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
228 Assert.AreEqual(max, achieved, "#1");
233 public void WaitAll_ManyTasks ()
235 for (int r = 0; r < 2000; ++r) {
236 var tasks = new Task[60];
238 for (int i = 0; i < tasks.Length; i++) {
239 tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
242 Assert.IsTrue (Task.WaitAll (tasks, 2000));
247 public void WaitAll_Zero ()
249 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 0), "#0");
250 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 10), "#1");
254 public void WaitAll_WithExceptions ()
256 InitWithDelegate (delegate { throw new ApplicationException (); });
259 Task.WaitAll (tasks);
261 } catch (AggregateException e) {
262 Assert.AreEqual (6, e.InnerExceptions.Count, "#2");
265 Assert.IsNotNull (tasks[0].Exception, "#3");
269 public void WaitAll_TimeoutWithExceptionsAfter ()
271 CountdownEvent cde = new CountdownEvent (2);
272 var mre = new ManualResetEvent (false);
274 Task.Factory.StartNew (delegate { mre.WaitOne (); }),
275 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
276 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
279 Assert.IsTrue (cde.Wait (1000), "#1");
280 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
285 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
287 } catch (AggregateException e) {
288 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
293 public void WaitAll_TimeoutWithExceptionsBefore ()
295 CountdownEvent cde = new CountdownEvent (2);
296 var mre = new ManualResetEvent (false);
298 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
299 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
300 Task.Factory.StartNew (delegate { mre.WaitOne (); })
303 Assert.IsTrue (cde.Wait (1000), "#1");
304 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
309 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
311 } catch (AggregateException e) {
312 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
317 public void WaitAll_Cancelled ()
319 var cancelation = new CancellationTokenSource ();
320 var tasks = new Task[] {
321 new Task (delegate { cancelation.Cancel (); }),
322 new Task (delegate { }, cancelation.Token)
328 Task.WaitAll (tasks);
330 } catch (AggregateException e) {
331 var inner = (TaskCanceledException) e.InnerException;
332 Assert.AreEqual (tasks[1], inner.Task, "#2");
335 Assert.IsTrue (tasks[0].IsCompleted, "#3");
336 Assert.IsTrue (tasks[1].IsCanceled, "#4");
341 public void WaitAll_CancelledAndTimeout ()
343 var ct = new CancellationToken (true);
344 var t1 = new Task (() => {}, ct);
345 var t2 = Task.Delay (3000);
346 Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
351 public void WaitAllExceptionThenCancelled ()
353 var cancelation = new CancellationTokenSource ();
354 var tasks = new Task[] {
355 new Task (delegate { cancelation.Cancel (); throw new ApplicationException (); }),
356 new Task (delegate { }, cancelation.Token)
362 Task.WaitAll (tasks);
364 } catch (AggregateException e) {
365 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#2");
366 var inner = (TaskCanceledException) e.InnerExceptions[1];
367 Assert.AreEqual (tasks[1], inner.Task, "#3");
370 Assert.IsTrue (tasks[0].IsCompleted, "#4");
371 Assert.IsTrue (tasks[1].IsCanceled, "#5");
375 public void WaitAll_StartedUnderWait ()
377 var task1 = new Task (delegate { });
379 ThreadPool.QueueUserWorkItem (delegate {
380 // Sleep little to let task to start and hit internal wait
385 Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
389 public void CancelBeforeStart ()
391 var src = new CancellationTokenSource ();
393 Task t = new Task (delegate { }, src.Token);
395 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
400 } catch (InvalidOperationException) {
405 public void Wait_CancelledTask ()
407 var src = new CancellationTokenSource ();
409 Task t = new Task (delegate { }, src.Token);
415 } catch (AggregateException e) {
416 var details = (TaskCanceledException) e.InnerException;
417 Assert.AreEqual (t, details.Task, "#1e");
423 } catch (AggregateException e) {
424 var details = (TaskCanceledException) e.InnerException;
425 Assert.AreEqual (t, details.Task, "#2e");
426 Assert.IsNull (details.Task.Exception, "#2e2");
431 public void Wait_Inlined ()
433 bool? previouslyQueued = null;
435 var scheduler = new MockScheduler ();
436 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
437 previouslyQueued = b;
440 var tf = new TaskFactory (scheduler);
441 var t = tf.StartNew (() => { });
444 Assert.AreEqual (true, previouslyQueued);
447 [Test, ExpectedException (typeof (InvalidOperationException))]
448 public void CreationWhileInitiallyCanceled ()
450 var token = new CancellationToken (true);
451 var task = new Task (() => { }, token);
452 Assert.AreEqual (TaskStatus.Canceled, task.Status);
457 public void ContinueWithInvalidArguments ()
459 var task = new Task (() => { });
461 task.ContinueWith (null);
463 } catch (ArgumentException) {
467 task.ContinueWith (delegate { }, null);
469 } catch (ArgumentException) {
473 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
475 } catch (ArgumentException) {
479 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
481 } catch (ArgumentException) {
486 public void ContinueWithOnAnyTestCase()
488 ParallelTestHelper.Repeat (delegate {
491 Task t = Task.Factory.StartNew(delegate { });
492 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
493 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
494 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
495 Assert.IsNull(cont.Exception, "#1");
496 Assert.IsNotNull(cont, "#2");
497 Assert.IsTrue(result, "#3");
502 public void ContinueWithOnCompletedSuccessfullyTestCase()
504 ParallelTestHelper.Repeat (delegate {
507 Task t = Task.Factory.StartNew(delegate { });
508 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
509 Assert.IsTrue (t.Wait(1000), "#4");
510 Assert.IsTrue (cont.Wait(1000), "#5");
512 Assert.IsNull(cont.Exception, "#1");
513 Assert.IsNotNull(cont, "#2");
514 Assert.IsTrue(result, "#3");
519 public void ContinueWithOnAbortedTestCase()
522 bool taskResult = false;
524 CancellationTokenSource src = new CancellationTokenSource ();
525 Task t = new Task (delegate { taskResult = true; }, src.Token);
527 Task cont = t.ContinueWith (delegate { result = true; },
528 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
532 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
533 Assert.IsTrue (cont.IsCompleted, "#1b");
534 Assert.IsTrue (result, "#1c");
539 } catch (InvalidOperationException) {
542 Assert.IsTrue (cont.Wait (1000), "#3");
544 Assert.IsFalse (taskResult, "#4");
546 Assert.IsNull (cont.Exception, "#5");
547 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
551 public void ContinueWithOnFailedTestCase()
553 ParallelTestHelper.Repeat (delegate {
556 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
557 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
559 Assert.IsTrue (cont.Wait(1000), "#0");
560 Assert.IsNotNull (t.Exception, "#1");
561 Assert.IsNotNull (cont, "#2");
562 Assert.IsTrue (result, "#3");
567 public void ContinueWithWithStart ()
569 Task t = new Task<int> (() => 1);
570 t = t.ContinueWith (l => { });
574 } catch (InvalidOperationException) {
579 public void ContinueWithChildren ()
581 ParallelTestHelper.Repeat (delegate {
584 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
586 var mre = new ManualResetEvent (false);
587 t.ContinueWith (l => {
592 Assert.IsTrue (mre.WaitOne (1000), "#1");
593 Assert.IsTrue (result, "#2");
598 public void ContinueWithDifferentOptionsAreCanceledTest ()
600 var mre = new ManualResetEventSlim ();
601 var task = Task.Factory.StartNew (() => mre.Wait (200));
602 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
603 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
604 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
607 contSuccess.Wait (100);
609 Assert.IsTrue (contSuccess.IsCompleted);
610 Assert.IsTrue (contFailed.IsCompleted);
611 Assert.IsTrue (contCanceled.IsCompleted);
612 Assert.IsFalse (contSuccess.IsCanceled);
613 Assert.IsTrue (contFailed.IsCanceled);
614 Assert.IsTrue (contCanceled.IsCanceled);
618 public void MultipleTasks()
620 ParallelTestHelper.Repeat (delegate {
621 bool r1 = false, r2 = false, r3 = false;
623 Task t1 = Task.Factory.StartNew(delegate {
626 Task t2 = Task.Factory.StartNew(delegate {
629 Task t3 = Task.Factory.StartNew(delegate {
637 Assert.IsTrue(r1, "#1");
638 Assert.IsTrue(r2, "#2");
639 Assert.IsTrue(r3, "#3");
644 public void WaitChildTestCase()
646 ParallelTestHelper.Repeat (delegate {
647 bool r1 = false, r2 = false, r3 = false;
648 var mre = new ManualResetEventSlim (false);
649 var mreStart = new ManualResetEventSlim (false);
651 Task t = Task.Factory.StartNew(delegate {
652 Task.Factory.StartNew(delegate {
655 }, TaskCreationOptions.AttachedToParent);
656 Task.Factory.StartNew(delegate {
658 }, TaskCreationOptions.AttachedToParent);
659 Task.Factory.StartNew(delegate {
661 }, TaskCreationOptions.AttachedToParent);
666 Assert.IsFalse (t.Wait (10), "#0a");
668 Assert.IsTrue (t.Wait (500), "#0b");
669 Assert.IsTrue(r2, "#1");
670 Assert.IsTrue(r3, "#2");
671 Assert.IsTrue(r1, "#3");
672 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
679 public void WaitingForChildrenToComplete ()
682 var mre = new ManualResetEvent (false);
684 parent_wfc = Task.Factory.StartNew (() => {
685 nested = Task.Factory.StartNew (() => {
686 Assert.IsTrue (mre.WaitOne (4000), "parent_wfc needs to be set first");
687 Assert.IsFalse (parent_wfc.Wait (10), "#1a");
688 Assert.AreEqual (TaskStatus.WaitingForChildrenToComplete, parent_wfc.Status, "#1b");
689 }, TaskCreationOptions.AttachedToParent).ContinueWith (l => {
690 Assert.IsTrue (parent_wfc.Wait (2000), "#2a");
691 Assert.AreEqual (TaskStatus.RanToCompletion, parent_wfc.Status, "#2b");
692 }, TaskContinuationOptions.ExecuteSynchronously);
696 Assert.IsTrue (parent_wfc.Wait (2000), "#3");
697 Assert.IsTrue (nested.Wait (2000), "#4");
701 public void WaitChildWithContinuationAttachedTest ()
704 var task = new Task(() =>
706 Task.Factory.StartNew(() => {
708 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
711 }, TaskContinuationOptions.AttachedToParent);
715 Assert.IsTrue (result);
719 public void WaitChildWithContinuationNotAttachedTest ()
721 var task = new Task(() =>
723 Task.Factory.StartNew(() => {
725 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
730 Assert.IsTrue (task.Wait(400));
734 public void WaitChildWithNesting ()
737 var t = Task.Factory.StartNew (() => {
738 Task.Factory.StartNew (() => {
739 Task.Factory.StartNew (() => {
742 }, TaskCreationOptions.AttachedToParent);
743 }, TaskCreationOptions.AttachedToParent);
746 Assert.IsTrue (result);
750 public void DoubleWaitTest ()
752 ParallelTestHelper.Repeat (delegate {
753 var evt = new ManualResetEventSlim ();
754 var t = Task.Factory.StartNew (() => evt.Wait (5000));
755 var cntd = new CountdownEvent (2);
756 var cntd2 = new CountdownEvent (2);
758 bool r1 = false, r2 = false;
759 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); });
760 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); });
762 Assert.IsTrue (cntd.Wait (2000), "#1");
764 Assert.IsTrue (cntd2.Wait (2000), "#2");
765 Assert.IsTrue (r1, "r1");
766 Assert.IsTrue (r2, "r2");
771 public void DoubleTimeoutedWaitTest ()
773 var evt = new ManualResetEventSlim ();
774 var t = new Task (delegate { });
775 var cntd = new CountdownEvent (2);
777 bool r1 = false, r2 = false;
778 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
779 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
787 public void RunSynchronously ()
790 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
791 t.RunSynchronously ();
793 Assert.AreEqual (1, val, "#1");
795 t = new Task (() => { Thread.Sleep (0); val = 2; });
797 bool? previouslyQueued = null;
799 var scheduler = new MockScheduler ();
800 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
801 previouslyQueued = b;
804 t.RunSynchronously (scheduler);
806 Assert.AreEqual (2, val, "#2");
807 Assert.AreEqual (false, previouslyQueued, "#2a");
811 public void RunSynchronouslyArgumentChecks ()
813 Task t = new Task (() => { });
815 t.RunSynchronously (null);
817 } catch (ArgumentNullException) {
822 public void RunSynchronouslyWithAttachedChildren ()
825 var t = new Task (() => {
826 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
828 t.RunSynchronously ();
829 Assert.IsTrue (result);
833 public void RunSynchronouslyOnContinuation ()
835 Task t = new Task<int> (() => 1);
836 t = t.ContinueWith (l => { });
838 t.RunSynchronously ();
840 } catch (InvalidOperationException) {
845 public void UnobservedExceptionOnFinalizerThreadTest ()
847 bool wasCalled = false;
848 TaskScheduler.UnobservedTaskException += (o, args) => {
852 var inner = new ApplicationException ();
853 Task.Factory.StartNew (() => { throw inner; });
857 GC.WaitForPendingFinalizers ();
859 Assert.IsTrue (wasCalled);
862 [Test, ExpectedException (typeof (InvalidOperationException))]
863 public void StartFinishedTaskTest ()
865 var t = Task.Factory.StartNew (delegate () { });
872 public void Start_NullArgument ()
874 var t = Task.Factory.StartNew (delegate () { });
878 } catch (ArgumentNullException) {
882 [Test, ExpectedException (typeof (InvalidOperationException))]
883 public void DisposeUnstartedTest ()
885 var t = new Task (() => { });
890 public void ThrowingUnrelatedCanceledExceptionTest ()
892 Task t = new Task (() => {
893 throw new TaskCanceledException ();
896 t.RunSynchronously ();
897 Assert.IsTrue (t.IsFaulted);
898 Assert.IsFalse (t.IsCanceled);
902 public void CanceledContinuationExecuteSynchronouslyTest ()
904 var source = new CancellationTokenSource();
905 var token = source.Token;
906 var evt = new ManualResetEventSlim ();
910 var task = Task.Factory.StartNew (() => evt.Wait (100));
911 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
918 } catch (Exception ex) {
922 Assert.IsTrue (task.IsCompleted);
923 Assert.IsTrue (cont.IsCanceled);
924 Assert.IsFalse (result);
925 Assert.IsTrue (thrown);
929 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
931 Task innerTask = null;
932 var testTask = new Task (() =>
934 innerTask = new Task (() =>
936 throw new InvalidOperationException ();
937 }, TaskCreationOptions.AttachedToParent);
938 innerTask.RunSynchronously ();
940 testTask.RunSynchronously ();
942 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
943 Assert.IsNotNull (innerTask);
944 Assert.IsTrue (innerTask.IsFaulted);
945 Assert.IsNotNull (testTask.Exception);
946 Assert.IsTrue (testTask.IsFaulted);
947 Assert.IsNotNull (innerTask.Exception);
951 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
953 var continuationRan = false;
954 var testTask = new Task (() =>
956 var task = new Task (() =>
958 throw new InvalidOperationException();
959 }, TaskCreationOptions.AttachedToParent);
960 task.RunSynchronously ();
962 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
963 testTask.RunSynchronously ();
964 onErrorTask.Wait (100);
965 Assert.IsTrue (continuationRan);
969 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
971 var continuationRan = false;
972 var testTask = new Task (() =>
974 var task = new Task (() =>
976 throw new InvalidOperationException();
977 }, TaskCreationOptions.AttachedToParent);
978 task.RunSynchronously();
980 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
981 testTask.RunSynchronously ();
982 Assert.IsTrue (onErrorTask.IsCompleted);
983 Assert.IsFalse (onErrorTask.IsFaulted);
984 Assert.IsFalse (continuationRan);
988 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
990 var continuationRan = false;
991 AggregateException e = null;
992 var testTask = new Task (() =>
994 var child1 = new Task (() =>
996 var child2 = new Task (() =>
998 throw new InvalidOperationException();
999 }, TaskCreationOptions.AttachedToParent);
1000 child2.RunSynchronously ();
1001 }, TaskCreationOptions.AttachedToParent);
1003 child1.RunSynchronously();
1004 e = child1.Exception;
1005 child1.Exception.Handle (ex => true);
1007 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1008 testTask.RunSynchronously ();
1009 onErrorTask.Wait (100);
1010 Assert.IsNotNull (e);
1011 Assert.IsTrue (continuationRan);
1015 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1017 string result = "Failed";
1018 var testTask = new Task (() =>
1020 var child = new Task<string> (() =>
1023 }, TaskCreationOptions.AttachedToParent);
1024 child.RunSynchronously ();
1025 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1027 testTask.RunSynchronously ();
1029 Assert.AreEqual ("Success", result);
1033 public void InlineNotTrashingParentRelationship ()
1035 bool r1 = false, r2 = false;
1036 var t = new Task (() => {
1037 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1038 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1040 t.RunSynchronously ();
1047 public void AsyncWaitHandleSet ()
1049 var task = new TaskFactory ().StartNew (() => { });
1050 var ar = (IAsyncResult)task;
1051 ar.AsyncWaitHandle.WaitOne ();
1056 public void Delay_Invalid ()
1060 } catch (ArgumentOutOfRangeException) {
1065 public void Delay_Start ()
1067 var t = Task.Delay (5000);
1070 } catch (InvalidOperationException) {
1075 public void Delay_Simple ()
1077 var t = Task.Delay (300);
1078 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1079 Assert.IsTrue (t.Wait (400), "#2");
1083 public void Delay_Cancelled ()
1085 var cancelation = new CancellationTokenSource ();
1087 var t = Task.Delay (5000, cancelation.Token);
1088 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1089 cancelation.Cancel ();
1093 } catch (AggregateException) {
1094 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1097 cancelation = new CancellationTokenSource ();
1098 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1099 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1100 cancelation.Cancel ();
1103 Assert.Fail ("#12");
1104 } catch (AggregateException) {
1105 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1110 public void WaitAny_WithNull ()
1112 var tasks = new [] {
1113 Task.FromResult (2),
1118 Task.WaitAny (tasks);
1120 } catch (ArgumentException) {
1125 public void WhenAll_WithNull ()
1128 Task.FromResult (2),
1133 Task.WhenAll (tasks);
1135 } catch (ArgumentException) {
1140 Task.WhenAll (tasks);
1142 } catch (ArgumentException) {
1147 public void WhenAll_Start ()
1149 Task[] tasks = new[] {
1150 Task.FromResult (2),
1153 var t = Task.WhenAll (tasks);
1154 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1159 } catch (InvalidOperationException) {
1163 new Task (delegate { }),
1166 t = Task.WhenAll (tasks);
1167 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1171 Assert.Fail ("#12");
1172 } catch (InvalidOperationException) {
1177 public void WhenAll_Cancelled ()
1179 var cancelation = new CancellationTokenSource ();
1180 var tasks = new Task[] {
1181 new Task (delegate { }),
1182 new Task (delegate { }, cancelation.Token)
1185 cancelation.Cancel ();
1187 var t = Task.WhenAll (tasks);
1188 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1192 Assert.IsTrue (t.Wait (1000), "#2");
1193 Assert.Fail ("#2a");
1194 } catch (AggregateException e) {
1195 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1200 public void WhenAll_Faulted ()
1202 var tcs = new TaskCompletionSource<object> ();
1203 tcs.SetException (new ApplicationException ());
1205 var tcs2 = new TaskCompletionSource<object> ();
1206 tcs2.SetException (new InvalidTimeZoneException ());
1208 var cancelation = new CancellationTokenSource ();
1209 var tasks = new Task[] {
1210 new Task (delegate { }),
1211 new Task (delegate { }, cancelation.Token),
1216 cancelation.Cancel ();
1218 var t = Task.WhenAll (tasks);
1219 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1223 Assert.IsTrue (t.Wait (1000), "#2");
1224 Assert.Fail ("#2a");
1225 } catch (AggregateException e) {
1226 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1227 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1232 public void WhenAll ()
1234 var t1 = new Task (delegate { });
1235 var t2 = new Task (delegate { t1.Start (); });
1237 var tasks = new Task[] {
1242 var t = Task.WhenAll (tasks);
1243 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1246 Assert.IsTrue (t.Wait (1000), "#2");
1250 public void WhenAllResult_WithNull ()
1253 Task.FromResult (2),
1258 Task.WhenAll<int> (tasks);
1260 } catch (ArgumentException) {
1265 Task.WhenAll<int> (tasks);
1267 } catch (ArgumentException) {
1272 public void WhenAllResult_Cancelled ()
1274 var cancelation = new CancellationTokenSource ();
1275 var tasks = new [] {
1276 new Task<int> (delegate { return 9; }),
1277 new Task<int> (delegate { return 1; }, cancelation.Token)
1280 cancelation.Cancel ();
1282 var t = Task.WhenAll (tasks);
1283 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1287 Assert.IsTrue (t.Wait (1000), "#2");
1288 Assert.Fail ("#2a");
1289 } catch (AggregateException e) {
1290 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1296 } catch (AggregateException) {
1301 public void WhenAllResult ()
1303 var t1 = new Task<string> (delegate { return "a"; });
1304 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1306 var tasks = new [] {
1311 var t = Task.WhenAll<string> (tasks);
1312 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1315 Assert.IsTrue (t.Wait (1000), "#2");
1316 Assert.AreEqual (2, t.Result.Length, "#3");
1317 Assert.AreEqual ("a", t.Result[0], "#3a");
1318 Assert.AreEqual ("b", t.Result[1], "#3b");
1322 public void WhenAllResult_Completed ()
1325 Task.FromResult (1),
1329 var t = Task.WhenAll<int> (tasks);
1330 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1331 Assert.AreEqual (2, t.Result.Length, "#2");
1332 Assert.AreEqual (1, t.Result[0], "#2a");
1333 Assert.AreEqual (2, t.Result[1], "#2b");
1337 public void WhenAny_WithNull ()
1339 var tasks = new Task[] {
1340 Task.FromResult (2),
1345 Task.WhenAny (tasks);
1347 } catch (ArgumentException) {
1352 Task.WhenAny (tasks);
1354 } catch (ArgumentException) {
1358 Task.WhenAny (new Task[0]);
1360 } catch (ArgumentException) {
1365 public void WhenAny_Start ()
1367 Task[] tasks = new[] {
1368 Task.FromResult (2),
1371 var t = Task.WhenAny (tasks);
1372 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1377 } catch (InvalidOperationException) {
1381 new Task (delegate { }),
1384 t = Task.WhenAny (tasks);
1385 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1389 Assert.Fail ("#12");
1390 } catch (InvalidOperationException) {
1395 public void WhenAny_Cancelled ()
1397 var cancelation = new CancellationTokenSource ();
1398 var tasks = new Task[] {
1399 new Task (delegate { }),
1400 new Task (delegate { }, cancelation.Token)
1403 cancelation.Cancel ();
1405 var t = Task.WhenAny (tasks);
1406 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1409 Assert.IsTrue (t.Wait (1000), "#2");
1410 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1414 public void WhenAny_Faulted ()
1416 var tcs = new TaskCompletionSource<object> ();
1417 tcs.SetException (new ApplicationException ());
1419 var tcs2 = new TaskCompletionSource<object> ();
1420 tcs2.SetException (new InvalidTimeZoneException ());
1422 var cancelation = new CancellationTokenSource ();
1423 var tasks = new Task[] {
1424 new Task (delegate { }),
1426 new Task (delegate { }, cancelation.Token),
1430 cancelation.Cancel ();
1432 var t = Task.WhenAny (tasks);
1433 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1436 Assert.IsTrue (t.Wait (1000), "#2");
1437 Assert.IsNull (t.Exception, "#3");
1439 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1443 public void WhenAny ()
1445 var t1 = new Task (delegate { });
1446 var t2 = new Task (delegate { t1.Start (); });
1448 var tasks = new Task[] {
1453 var t = Task.WhenAny (tasks);
1454 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1457 Assert.IsTrue (t.Wait (1000), "#2");
1458 Assert.IsNotNull (t.Result, "#3");
1462 public void WhenAnyResult_WithNull ()
1464 var tasks = new [] {
1465 Task.FromResult (2),
1470 Task.WhenAny<int> (tasks);
1472 } catch (ArgumentException) {
1477 Task.WhenAny<int> (tasks);
1479 } catch (ArgumentException) {
1483 Task.WhenAny<short> (new Task<short>[0]);
1485 } catch (ArgumentException) {
1490 public void WhenAnyResult_Start ()
1493 Task.FromResult (2),
1496 var t = Task.WhenAny<int> (tasks);
1497 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1502 } catch (InvalidOperationException) {
1506 new Task<int> (delegate { return 55; }),
1509 t = Task.WhenAny<int> (tasks);
1510 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1514 Assert.Fail ("#12");
1515 } catch (InvalidOperationException) {
1520 public void WhenAnyResult_Cancelled ()
1522 var cancelation = new CancellationTokenSource ();
1523 var tasks = new [] {
1524 new Task<double> (delegate { return 1.1; }),
1525 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1528 cancelation.Cancel ();
1530 var t = Task.WhenAny<double> (tasks);
1531 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1534 Assert.IsTrue (t.Wait (1000), "#2");
1535 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1539 public void WhenAnyResult_Faulted ()
1541 var tcs = new TaskCompletionSource<object> ();
1542 tcs.SetException (new ApplicationException ());
1544 var tcs2 = new TaskCompletionSource<object> ();
1545 tcs2.SetException (new InvalidTimeZoneException ());
1547 var cancelation = new CancellationTokenSource ();
1548 var tasks = new Task<object>[] {
1549 new Task<object> (delegate { return null; }),
1551 new Task<object> (delegate { return ""; }, cancelation.Token),
1555 cancelation.Cancel ();
1557 var t = Task.WhenAny<object> (tasks);
1558 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1561 Assert.IsTrue (t.Wait (1000), "#2");
1562 Assert.IsNull (t.Exception, "#3");
1564 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1568 public void WhenAnyResult ()
1570 var t1 = new Task<byte> (delegate { return 3; });
1571 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1573 var tasks = new [] {
1578 var t = Task.WhenAny<byte> (tasks);
1579 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1582 Assert.IsTrue (t.Wait (1000), "#2");
1583 Assert.IsTrue (t.Result.Result > 1, "#3");
1587 public void ContinueWith_StateValue ()
1589 var t = Task.Factory.StartNew (l => {
1590 Assert.AreEqual (1, l, "a-1");
1593 var c = t.ContinueWith ((a, b) => {
1594 Assert.AreEqual (t, a, "c-1");
1595 Assert.AreEqual (2, b, "c-2");
1598 var d = t.ContinueWith ((a, b) => {
1599 Assert.AreEqual (t, a, "d-1");
1600 Assert.AreEqual (3, b, "d-2");
1604 Assert.IsTrue (d.Wait (1000), "#1");
1606 Assert.AreEqual (1, t.AsyncState, "#2");
1607 Assert.AreEqual (2, c.AsyncState, "#3");
1608 Assert.AreEqual (3, d.AsyncState, "#4");
1612 public void ContinueWith_StateValueGeneric ()
1614 var t = Task<int>.Factory.StartNew (l => {
1615 Assert.AreEqual (1, l, "a-1");
1619 var c = t.ContinueWith ((a, b) => {
1620 Assert.AreEqual (t, a, "c-1");
1621 Assert.AreEqual (2, b, "c-2");
1625 var d = t.ContinueWith ((a, b) => {
1626 Assert.AreEqual (t, a, "d-1");
1627 Assert.AreEqual (3, b, "d-2");
1631 Assert.IsTrue (d.Wait (1000), "#1");
1633 Assert.AreEqual (1, t.AsyncState, "#2");
1634 Assert.AreEqual (80, t.Result, "#2r");
1635 Assert.AreEqual (2, c.AsyncState, "#3");
1636 Assert.AreEqual ("c", c.Result, "#3r");
1637 Assert.AreEqual (3, d.AsyncState, "#4");
1638 Assert.AreEqual ('d', d.Result, "#3r");
1642 public void FromResult ()
1644 var t = Task.FromResult<object> (null);
1645 Assert.IsTrue (t.IsCompleted, "#1");
1646 Assert.AreEqual (null, t.Result, "#2");
1652 public void LongRunning ()
1656 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1658 Assert.IsTrue (t.Wait (100));
1659 Assert.IsTrue ((bool)is_tp, "#1");
1660 Assert.IsTrue ((bool)is_bg, "#2");
1664 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1667 Assert.IsTrue (t.Wait (100));
1668 Assert.IsFalse ((bool) is_tp, "#11");
1669 Assert.IsTrue ((bool) is_bg, "#12");
1673 public void Run_ArgumentCheck ()
1676 Task.Run (null as Action);
1678 } catch (ArgumentNullException) {
1685 bool ranOnDefaultScheduler = false;
1686 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1687 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1689 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1693 public void Run_Cancel ()
1695 var t = Task.Run (() => 1, new CancellationToken (true));
1699 } catch (AggregateException) {
1702 Assert.IsTrue (t.IsCanceled, "#2");
1706 public void Run_ExistingTaskT ()
1708 var t = new Task<int> (() => 5);
1709 var t2 = Task.Run (() => { t.Start (); return t; });
1711 Assert.IsTrue (t2.Wait (1000), "#1");
1712 Assert.AreEqual (5, t2.Result, "#2");
1716 public void Run_ExistingTask ()
1718 var t = new Task (delegate { throw new Exception ("Foo"); });
1719 var t2 = Task.Run (() => { t.Start (); return t; });
1724 } catch (Exception) {}
1726 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1730 public void DenyChildAttachTest ()
1732 var mre = new ManualResetEventSlim ();
1734 Task parent = Task.Factory.StartNew (() => {
1735 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1736 }, TaskCreationOptions.DenyChildAttach);
1737 Assert.IsTrue (parent.Wait (1000), "#1");
1739 Assert.IsTrue (nested.Wait (2000), "#2");
1742 class SynchronousScheduler : TaskScheduler
1744 protected override IEnumerable<Task> GetScheduledTasks ()
1746 throw new NotImplementedException ();
1749 protected override void QueueTask (Task task)
1751 TryExecuteTaskInline (task, false);
1754 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1756 return base.TryExecuteTask (task);
1761 public void HideSchedulerTest ()
1763 var mre = new ManualResetEventSlim ();
1764 var ranOnDefault = false;
1765 var scheduler = new SynchronousScheduler ();
1767 Task parent = Task.Factory.StartNew (() => {
1768 Task.Factory.StartNew (() => {
1769 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1772 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
1774 Assert.IsTrue (mre.Wait (1000), "#1");
1775 Assert.IsTrue (ranOnDefault, "#2");
1779 public void LazyCancelationTest ()
1781 var source = new CancellationTokenSource ();
1783 var parent = new Task (delegate {});
1784 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
1786 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
1789 Assert.IsTrue (cont.Wait (1000), "#2");
1791 } catch (AggregateException ex) {
1792 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");