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;
38 namespace MonoTests.System.Threading.Tasks
41 public class TaskTests
43 class MockScheduler : TaskScheduler
45 public event Action<Task, bool> TryExecuteTaskInlineHandler;
47 protected override IEnumerable<Task> GetScheduledTasks ()
49 throw new NotImplementedException ();
52 protected override void QueueTask (Task task)
57 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
59 if (TryExecuteTaskInlineHandler != null)
60 TryExecuteTaskInlineHandler (task, taskWasPreviouslyQueued);
62 return base.TryExecuteTask (task);
73 tasks = new Task[max];
76 void InitWithDelegate(Action action)
78 for (int i = 0; i < max; i++) {
79 tasks[i] = Task.Factory.StartNew(action);
84 public void WaitAnyTest()
86 ParallelTestHelper.Repeat (delegate {
90 InitWithDelegate(delegate {
91 int times = Interlocked.Exchange (ref flag, 1);
93 SpinWait sw = new SpinWait ();
94 while (finished == 0) sw.SpinOnce ();
96 Interlocked.Increment (ref finished);
100 int index = Task.WaitAny(tasks, 1000);
102 Assert.AreNotEqual (-1, index, "#3");
103 Assert.AreEqual (1, flag, "#1");
104 Assert.AreEqual (1, finished, "#2");
109 public void WaitAny_Empty ()
111 Assert.AreEqual (-1, Task.WaitAny (new Task[0]));
115 public void WaitAny_Zero ()
117 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { })}, 0), "#1");
118 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { }) }, 20), "#1");
122 public void WaitAny_Cancelled ()
124 var cancelation = new CancellationTokenSource ();
125 var tasks = new Task[] {
126 new Task (delegate { }),
127 new Task (delegate { }, cancelation.Token)
130 cancelation.Cancel ();
132 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
133 Assert.IsTrue (tasks[1].IsCompleted, "#2");
134 Assert.IsTrue (tasks[1].IsCanceled, "#3");
138 public void WaitAny_CancelledWithoutExecution ()
140 var cancelation = new CancellationTokenSource ();
141 var tasks = new Task[] {
142 new Task (delegate { }),
143 new Task (delegate { })
147 var mre = new ManualResetEventSlim (false);
148 ThreadPool.QueueUserWorkItem (delegate {
149 res = Task.WaitAny (tasks, 20);
153 cancelation.Cancel ();
154 Assert.IsTrue (mre.Wait (1000), "#1");
155 Assert.AreEqual (-1, res);
159 public void WaitAny_OneException ()
161 var mre = new ManualResetEventSlim (false);
162 var tasks = new Task[] {
163 Task.Factory.StartNew (delegate { mre.Wait (1000); }),
164 Task.Factory.StartNew (delegate { throw new ApplicationException (); })
167 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
168 Assert.IsFalse (tasks[0].IsCompleted, "#2");
169 Assert.IsTrue (tasks[1].IsFaulted, "#3");
175 public void WaitAny_SingleCanceled ()
177 var src = new CancellationTokenSource ();
178 var t = Task.Factory.StartNew (() => { Thread.Sleep (200); src.Cancel (); src.Token.ThrowIfCancellationRequested (); }, src.Token);
179 Assert.AreEqual (0, Task.WaitAny (new [] { t }));
182 public void WaitAny_ManyExceptions ()
184 CountdownEvent cde = new CountdownEvent (3);
186 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
187 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
188 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
191 Assert.IsTrue (cde.Wait (1000), "#1");
194 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#2");
195 } catch (AggregateException e) {
196 Assert.AreEqual (3, e.InnerExceptions.Count, "#3");
201 public void WaitAny_ManyCanceled ()
203 var cancellation = new CancellationToken (true);
205 Task.Factory.StartNew (delegate { }, cancellation),
206 Task.Factory.StartNew (delegate { }, cancellation),
207 Task.Factory.StartNew (delegate { }, cancellation)
211 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#1");
212 } catch (AggregateException e) {
213 Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
218 public void WaitAllTest ()
220 ParallelTestHelper.Repeat (delegate {
222 InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
224 Assert.AreEqual(max, achieved, "#1");
229 public void WaitAll_ManyTasks ()
231 for (int r = 0; r < 2000; ++r) {
232 var tasks = new Task[60];
234 for (int i = 0; i < tasks.Length; i++) {
235 tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
238 Assert.IsTrue (Task.WaitAll (tasks, 2000));
243 public void WaitAll_Zero ()
245 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 0), "#0");
246 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 10), "#1");
250 public void WaitAll_WithExceptions ()
252 InitWithDelegate (delegate { throw new ApplicationException (); });
255 Task.WaitAll (tasks);
257 } catch (AggregateException e) {
258 Assert.AreEqual (6, e.InnerExceptions.Count, "#2");
261 Assert.IsNotNull (tasks[0].Exception, "#3");
265 public void WaitAll_TimeoutWithExceptionsAfter ()
267 CountdownEvent cde = new CountdownEvent (2);
268 var mre = new ManualResetEvent (false);
270 Task.Factory.StartNew (delegate { mre.WaitOne (); }),
271 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
272 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
275 Assert.IsTrue (cde.Wait (1000), "#1");
276 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
281 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
283 } catch (AggregateException e) {
284 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
289 public void WaitAll_TimeoutWithExceptionsBefore ()
291 CountdownEvent cde = new CountdownEvent (2);
292 var mre = new ManualResetEvent (false);
294 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
295 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
296 Task.Factory.StartNew (delegate { mre.WaitOne (); })
299 Assert.IsTrue (cde.Wait (1000), "#1");
300 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
305 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
307 } catch (AggregateException e) {
308 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
313 public void WaitAll_Cancelled ()
315 var cancelation = new CancellationTokenSource ();
316 var tasks = new Task[] {
317 new Task (delegate { cancelation.Cancel (); }),
318 new Task (delegate { }, cancelation.Token)
324 Task.WaitAll (tasks);
326 } catch (AggregateException e) {
327 var inner = (TaskCanceledException) e.InnerException;
328 Assert.AreEqual (tasks[1], inner.Task, "#2");
331 Assert.IsTrue (tasks[0].IsCompleted, "#3");
332 Assert.IsTrue (tasks[1].IsCanceled, "#4");
337 public void WaitAll_CancelledAndTimeout ()
339 var ct = new CancellationToken (true);
340 var t1 = new Task (() => {}, ct);
341 var t2 = Task.Delay (3000);
342 Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
347 public void WaitAllExceptionThenCancelled ()
349 var cancelation = new CancellationTokenSource ();
350 var tasks = new Task[] {
351 new Task (delegate { cancelation.Cancel (); throw new ApplicationException (); }),
352 new Task (delegate { }, cancelation.Token)
358 Task.WaitAll (tasks);
360 } catch (AggregateException e) {
361 Assert.IsInstanceOfType (typeof (ApplicationException), e.InnerException, "#2");
362 var inner = (TaskCanceledException) e.InnerExceptions[1];
363 Assert.AreEqual (tasks[1], inner.Task, "#3");
366 Assert.IsTrue (tasks[0].IsCompleted, "#4");
367 Assert.IsTrue (tasks[1].IsCanceled, "#5");
371 public void WaitAll_StartedUnderWait ()
373 var task1 = new Task (delegate { });
375 ThreadPool.QueueUserWorkItem (delegate {
376 // Sleep little to let task to start and hit internal wait
381 Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
385 public void CancelBeforeStart ()
387 var src = new CancellationTokenSource ();
389 Task t = new Task (delegate { }, src.Token);
391 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
396 } catch (InvalidOperationException) {
401 public void Wait_CancelledTask ()
403 var src = new CancellationTokenSource ();
405 Task t = new Task (delegate { }, src.Token);
411 } catch (AggregateException e) {
412 var details = (TaskCanceledException) e.InnerException;
413 Assert.AreEqual (t, details.Task, "#1e");
419 } catch (AggregateException e) {
420 var details = (TaskCanceledException) e.InnerException;
421 Assert.AreEqual (t, details.Task, "#2e");
422 Assert.IsNull (details.Task.Exception, "#2e2");
427 public void Wait_Inlined ()
429 bool? previouslyQueued = null;
431 var scheduler = new MockScheduler ();
432 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
433 previouslyQueued = b;
436 var tf = new TaskFactory (scheduler);
437 var t = tf.StartNew (() => { });
440 Assert.AreEqual (true, previouslyQueued);
443 [Test, ExpectedException (typeof (InvalidOperationException))]
444 public void CreationWhileInitiallyCanceled ()
446 var token = new CancellationToken (true);
447 var task = new Task (() => { }, token);
448 Assert.AreEqual (TaskStatus.Canceled, task.Status);
453 public void ContinueWithInvalidArguments ()
455 var task = new Task (() => { });
457 task.ContinueWith (null);
459 } catch (ArgumentException) {
463 task.ContinueWith (delegate { }, null);
465 } catch (ArgumentException) {
469 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
471 } catch (ArgumentException) {
475 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
477 } catch (ArgumentException) {
482 public void ContinueWithOnAnyTestCase()
484 ParallelTestHelper.Repeat (delegate {
487 Task t = Task.Factory.StartNew(delegate { });
488 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
489 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
490 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
491 Assert.IsNull(cont.Exception, "#1");
492 Assert.IsNotNull(cont, "#2");
493 Assert.IsTrue(result, "#3");
498 public void ContinueWithOnCompletedSuccessfullyTestCase()
500 ParallelTestHelper.Repeat (delegate {
503 Task t = Task.Factory.StartNew(delegate { });
504 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
505 Assert.IsTrue (t.Wait(1000), "#4");
506 Assert.IsTrue (cont.Wait(1000), "#5");
508 Assert.IsNull(cont.Exception, "#1");
509 Assert.IsNotNull(cont, "#2");
510 Assert.IsTrue(result, "#3");
515 public void ContinueWithOnAbortedTestCase()
518 bool taskResult = false;
520 CancellationTokenSource src = new CancellationTokenSource ();
521 Task t = new Task (delegate { taskResult = true; }, src.Token);
523 Task cont = t.ContinueWith (delegate { result = true; },
524 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
528 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
529 Assert.IsTrue (cont.IsCompleted, "#1b");
530 Assert.IsTrue (result, "#1c");
535 } catch (InvalidOperationException) {
538 Assert.IsTrue (cont.Wait (1000), "#3");
540 Assert.IsFalse (taskResult, "#4");
542 Assert.IsNull (cont.Exception, "#5");
543 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
547 public void ContinueWithOnFailedTestCase()
549 ParallelTestHelper.Repeat (delegate {
552 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
553 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
555 Assert.IsTrue (cont.Wait(1000), "#0");
556 Assert.IsNotNull (t.Exception, "#1");
557 Assert.IsNotNull (cont, "#2");
558 Assert.IsTrue (result, "#3");
563 public void ContinueWithWithStart ()
565 Task t = new Task<int> (() => 1);
566 t = t.ContinueWith (l => { });
570 } catch (InvalidOperationException) {
575 public void ContinueWithChildren ()
577 ParallelTestHelper.Repeat (delegate {
580 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
582 var mre = new ManualResetEvent (false);
583 t.ContinueWith (l => {
588 Assert.IsTrue (mre.WaitOne (1000), "#1");
589 Assert.IsTrue (result, "#2");
594 public void ContinueWithDifferentOptionsAreCanceledTest ()
596 var mre = new ManualResetEventSlim ();
597 var task = Task.Factory.StartNew (() => mre.Wait (200));
598 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
599 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
600 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
603 contSuccess.Wait (100);
605 Assert.IsTrue (contSuccess.IsCompleted);
606 Assert.IsTrue (contFailed.IsCompleted);
607 Assert.IsTrue (contCanceled.IsCompleted);
608 Assert.IsFalse (contSuccess.IsCanceled);
609 Assert.IsTrue (contFailed.IsCanceled);
610 Assert.IsTrue (contCanceled.IsCanceled);
614 public void MultipleTasks()
616 ParallelTestHelper.Repeat (delegate {
617 bool r1 = false, r2 = false, r3 = false;
619 Task t1 = Task.Factory.StartNew(delegate {
622 Task t2 = Task.Factory.StartNew(delegate {
625 Task t3 = Task.Factory.StartNew(delegate {
633 Assert.IsTrue(r1, "#1");
634 Assert.IsTrue(r2, "#2");
635 Assert.IsTrue(r3, "#3");
640 public void WaitChildTestCase()
642 ParallelTestHelper.Repeat (delegate {
643 bool r1 = false, r2 = false, r3 = false;
644 var mre = new ManualResetEventSlim (false);
645 var mreStart = new ManualResetEventSlim (false);
647 Task t = Task.Factory.StartNew(delegate {
648 Task.Factory.StartNew(delegate {
651 }, TaskCreationOptions.AttachedToParent);
652 Task.Factory.StartNew(delegate {
654 }, TaskCreationOptions.AttachedToParent);
655 Task.Factory.StartNew(delegate {
657 }, TaskCreationOptions.AttachedToParent);
662 Assert.IsFalse (t.Wait (10), "#0a");
664 Assert.IsTrue (t.Wait (500), "#0b");
665 Assert.IsTrue(r2, "#1");
666 Assert.IsTrue(r3, "#2");
667 Assert.IsTrue(r1, "#3");
668 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
673 public void WaitChildWithContinuationAttachedTest ()
676 var task = new Task(() =>
678 Task.Factory.StartNew(() => {
680 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
683 }, TaskContinuationOptions.AttachedToParent);
687 Assert.IsTrue (result);
691 public void WaitChildWithContinuationNotAttachedTest ()
693 var task = new Task(() =>
695 Task.Factory.StartNew(() => {
697 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
702 Assert.IsTrue (task.Wait(400));
706 public void WaitChildWithNesting ()
709 var t = Task.Factory.StartNew (() => {
710 Task.Factory.StartNew (() => {
711 Task.Factory.StartNew (() => {
714 }, TaskCreationOptions.AttachedToParent);
715 }, TaskCreationOptions.AttachedToParent);
718 Assert.IsTrue (result);
722 public void DoubleWaitTest ()
724 ParallelTestHelper.Repeat (delegate {
725 var evt = new ManualResetEventSlim ();
726 var t = Task.Factory.StartNew (() => evt.Wait (5000));
727 var cntd = new CountdownEvent (2);
728 var cntd2 = new CountdownEvent (2);
730 bool r1 = false, r2 = false;
731 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); });
732 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); });
734 Assert.IsTrue (cntd.Wait (2000), "#1");
736 Assert.IsTrue (cntd2.Wait (2000), "#2");
737 Assert.IsTrue (r1, "r1");
738 Assert.IsTrue (r2, "r2");
743 public void DoubleTimeoutedWaitTest ()
745 var evt = new ManualResetEventSlim ();
746 var t = new Task (delegate { });
747 var cntd = new CountdownEvent (2);
749 bool r1 = false, r2 = false;
750 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
751 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
759 public void RunSynchronously ()
762 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
763 t.RunSynchronously ();
765 Assert.AreEqual (1, val, "#1");
767 t = new Task (() => { Thread.Sleep (0); val = 2; });
769 bool? previouslyQueued = null;
771 var scheduler = new MockScheduler ();
772 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
773 previouslyQueued = b;
776 t.RunSynchronously (scheduler);
778 Assert.AreEqual (2, val, "#2");
779 Assert.AreEqual (false, previouslyQueued, "#2a");
783 public void RunSynchronouslyArgumentChecks ()
785 Task t = new Task (() => { });
787 t.RunSynchronously (null);
789 } catch (ArgumentNullException) {
794 public void RunSynchronouslyWithAttachedChildren ()
797 var t = new Task (() => {
798 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
800 t.RunSynchronously ();
801 Assert.IsTrue (result);
805 public void UnobservedExceptionOnFinalizerThreadTest ()
807 bool wasCalled = false;
808 TaskScheduler.UnobservedTaskException += (o, args) => {
812 var inner = new ApplicationException ();
813 Task.Factory.StartNew (() => { throw inner; });
817 GC.WaitForPendingFinalizers ();
819 Assert.IsTrue (wasCalled);
822 [Test, ExpectedException (typeof (InvalidOperationException))]
823 public void StartFinishedTaskTest ()
825 var t = Task.Factory.StartNew (delegate () { });
832 public void Start_NullArgument ()
834 var t = Task.Factory.StartNew (delegate () { });
838 } catch (ArgumentNullException) {
842 [Test, ExpectedException (typeof (InvalidOperationException))]
843 public void DisposeUnstartedTest ()
845 var t = new Task (() => { });
850 public void ThrowingUnrelatedCanceledExceptionTest ()
852 Task t = new Task (() => {
853 throw new TaskCanceledException ();
856 t.RunSynchronously ();
857 Assert.IsTrue (t.IsFaulted);
858 Assert.IsFalse (t.IsCanceled);
862 public void CanceledContinuationExecuteSynchronouslyTest ()
864 var source = new CancellationTokenSource();
865 var token = source.Token;
866 var evt = new ManualResetEventSlim ();
870 var task = Task.Factory.StartNew (() => evt.Wait (100));
871 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
878 } catch (Exception ex) {
882 Assert.IsTrue (task.IsCompleted);
883 Assert.IsTrue (cont.IsCanceled);
884 Assert.IsFalse (result);
885 Assert.IsTrue (thrown);
889 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
891 Task innerTask = null;
892 var testTask = new Task (() =>
894 innerTask = new Task (() =>
896 throw new InvalidOperationException ();
897 }, TaskCreationOptions.AttachedToParent);
898 innerTask.RunSynchronously ();
900 testTask.RunSynchronously ();
902 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
903 Assert.IsNotNull (innerTask);
904 Assert.IsTrue (innerTask.IsFaulted);
905 Assert.IsNotNull (testTask.Exception);
906 Assert.IsTrue (testTask.IsFaulted);
907 Assert.IsNotNull (innerTask.Exception);
911 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
913 var continuationRan = false;
914 var testTask = new Task (() =>
916 var task = new Task (() =>
918 throw new InvalidOperationException();
919 }, TaskCreationOptions.AttachedToParent);
920 task.RunSynchronously ();
922 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
923 testTask.RunSynchronously ();
924 onErrorTask.Wait (100);
925 Assert.IsTrue (continuationRan);
929 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
931 var continuationRan = false;
932 var testTask = new Task (() =>
934 var task = new Task (() =>
936 throw new InvalidOperationException();
937 }, TaskCreationOptions.AttachedToParent);
938 task.RunSynchronously();
940 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
941 testTask.RunSynchronously ();
942 Assert.IsTrue (onErrorTask.IsCompleted);
943 Assert.IsFalse (onErrorTask.IsFaulted);
944 Assert.IsFalse (continuationRan);
948 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
950 var continuationRan = false;
951 AggregateException e = null;
952 var testTask = new Task (() =>
954 var child1 = new Task (() =>
956 var child2 = new Task (() =>
958 throw new InvalidOperationException();
959 }, TaskCreationOptions.AttachedToParent);
960 child2.RunSynchronously ();
961 }, TaskCreationOptions.AttachedToParent);
963 child1.RunSynchronously();
964 e = child1.Exception;
965 child1.Exception.Handle (ex => true);
967 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
968 testTask.RunSynchronously ();
969 onErrorTask.Wait (100);
970 Assert.IsNotNull (e);
971 Assert.IsTrue (continuationRan);
975 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
977 string result = "Failed";
978 var testTask = new Task (() =>
980 var child = new Task<string> (() =>
983 }, TaskCreationOptions.AttachedToParent);
984 child.RunSynchronously ();
985 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
987 testTask.RunSynchronously ();
989 Assert.AreEqual ("Success", result);
993 public void InlineNotTrashingParentRelationship ()
995 bool r1 = false, r2 = false;
996 var t = new Task (() => {
997 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
998 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1000 t.RunSynchronously ();
1008 public void Delay_Invalid ()
1012 } catch (ArgumentOutOfRangeException) {
1017 public void Delay_Start ()
1019 var t = Task.Delay (5000);
1022 } catch (InvalidOperationException) {
1027 public void Delay_Simple ()
1029 var t = Task.Delay (300);
1030 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1031 Assert.IsTrue (t.Wait (400), "#2");
1035 public void Delay_Cancelled ()
1037 var cancelation = new CancellationTokenSource ();
1039 var t = Task.Delay (5000, cancelation.Token);
1040 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1041 cancelation.Cancel ();
1045 } catch (AggregateException) {
1046 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1049 cancelation = new CancellationTokenSource ();
1050 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1051 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1052 cancelation.Cancel ();
1055 Assert.Fail ("#12");
1056 } catch (AggregateException) {
1057 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1062 public void WaitAny_WithNull ()
1064 var tasks = new [] {
1065 Task.FromResult (2),
1070 Task.WaitAny (tasks);
1072 } catch (ArgumentException) {
1077 public void WhenAll_WithNull ()
1080 Task.FromResult (2),
1085 Task.WhenAll (tasks);
1087 } catch (ArgumentException) {
1092 Task.WhenAll (tasks);
1094 } catch (ArgumentException) {
1099 public void WhenAll_Start ()
1101 Task[] tasks = new[] {
1102 Task.FromResult (2),
1105 var t = Task.WhenAll (tasks);
1106 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1111 } catch (InvalidOperationException) {
1115 new Task (delegate { }),
1118 t = Task.WhenAll (tasks);
1119 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1123 Assert.Fail ("#12");
1124 } catch (InvalidOperationException) {
1129 public void WhenAll_Cancelled ()
1131 var cancelation = new CancellationTokenSource ();
1132 var tasks = new Task[] {
1133 new Task (delegate { }),
1134 new Task (delegate { }, cancelation.Token)
1137 cancelation.Cancel ();
1139 var t = Task.WhenAll (tasks);
1140 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1144 Assert.IsTrue (t.Wait (1000), "#2");
1145 Assert.Fail ("#2a");
1146 } catch (AggregateException e) {
1147 Assert.IsInstanceOfType (typeof (TaskCanceledException), e.InnerException, "#3");
1152 public void WhenAll_Faulted ()
1154 var tcs = new TaskCompletionSource<object> ();
1155 tcs.SetException (new ApplicationException ());
1157 var tcs2 = new TaskCompletionSource<object> ();
1158 tcs2.SetException (new InvalidTimeZoneException ());
1160 var cancelation = new CancellationTokenSource ();
1161 var tasks = new Task[] {
1162 new Task (delegate { }),
1163 new Task (delegate { }, cancelation.Token),
1168 cancelation.Cancel ();
1170 var t = Task.WhenAll (tasks);
1171 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1175 Assert.IsTrue (t.Wait (1000), "#2");
1176 Assert.Fail ("#2a");
1177 } catch (AggregateException e) {
1178 Assert.IsInstanceOfType (typeof (ApplicationException), e.InnerException, "#3");
1179 Assert.IsInstanceOfType (typeof (InvalidTimeZoneException), e.InnerExceptions[1], "#4");
1184 public void WhenAll ()
1186 var t1 = new Task (delegate { });
1187 var t2 = new Task (delegate { t1.Start (); });
1189 var tasks = new Task[] {
1194 var t = Task.WhenAll (tasks);
1195 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1198 Assert.IsTrue (t.Wait (1000), "#2");
1202 public void WhenAllResult_WithNull ()
1205 Task.FromResult (2),
1210 Task.WhenAll<int> (tasks);
1212 } catch (ArgumentException) {
1217 Task.WhenAll<int> (tasks);
1219 } catch (ArgumentException) {
1224 public void WhenAllResult_Cancelled ()
1226 var cancelation = new CancellationTokenSource ();
1227 var tasks = new [] {
1228 new Task<int> (delegate { return 9; }),
1229 new Task<int> (delegate { return 1; }, cancelation.Token)
1232 cancelation.Cancel ();
1234 var t = Task.WhenAll (tasks);
1235 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1239 Assert.IsTrue (t.Wait (1000), "#2");
1240 Assert.Fail ("#2a");
1241 } catch (AggregateException e) {
1242 Assert.IsInstanceOfType (typeof (TaskCanceledException), e.InnerException, "#3");
1248 } catch (AggregateException) {
1253 public void WhenAllResult ()
1255 var t1 = new Task<string> (delegate { return "a"; });
1256 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1258 var tasks = new [] {
1263 var t = Task.WhenAll<string> (tasks);
1264 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1267 Assert.IsTrue (t.Wait (1000), "#2");
1268 Assert.AreEqual (2, t.Result.Length, "#3");
1269 Assert.AreEqual ("a", t.Result[0], "#3a");
1270 Assert.AreEqual ("b", t.Result[1], "#3b");
1274 public void WhenAllResult_Completed ()
1277 Task.FromResult (1),
1281 var t = Task.WhenAll<int> (tasks);
1282 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1283 Assert.AreEqual (2, t.Result.Length, "#2");
1284 Assert.AreEqual (1, t.Result[0], "#2a");
1285 Assert.AreEqual (2, t.Result[1], "#2b");
1289 public void WhenAny_WithNull ()
1291 var tasks = new Task[] {
1292 Task.FromResult (2),
1297 Task.WhenAny (tasks);
1299 } catch (ArgumentException) {
1304 Task.WhenAny (tasks);
1306 } catch (ArgumentException) {
1310 Task.WhenAny (new Task[0]);
1312 } catch (ArgumentException) {
1317 public void WhenAny_Start ()
1319 Task[] tasks = new[] {
1320 Task.FromResult (2),
1323 var t = Task.WhenAny (tasks);
1324 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1329 } catch (InvalidOperationException) {
1333 new Task (delegate { }),
1336 t = Task.WhenAny (tasks);
1337 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1341 Assert.Fail ("#12");
1342 } catch (InvalidOperationException) {
1347 public void WhenAny_Cancelled ()
1349 var cancelation = new CancellationTokenSource ();
1350 var tasks = new Task[] {
1351 new Task (delegate { }),
1352 new Task (delegate { }, cancelation.Token)
1355 cancelation.Cancel ();
1357 var t = Task.WhenAny (tasks);
1358 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1361 Assert.IsTrue (t.Wait (1000), "#2");
1362 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1366 public void WhenAny_Faulted ()
1368 var tcs = new TaskCompletionSource<object> ();
1369 tcs.SetException (new ApplicationException ());
1371 var tcs2 = new TaskCompletionSource<object> ();
1372 tcs2.SetException (new InvalidTimeZoneException ());
1374 var cancelation = new CancellationTokenSource ();
1375 var tasks = new Task[] {
1376 new Task (delegate { }),
1378 new Task (delegate { }, cancelation.Token),
1382 cancelation.Cancel ();
1384 var t = Task.WhenAny (tasks);
1385 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1388 Assert.IsTrue (t.Wait (1000), "#2");
1389 Assert.IsNull (t.Exception, "#3");
1391 Assert.IsInstanceOfType (typeof (ApplicationException), t.Result.Exception.InnerException, "#4");
1395 public void WhenAny ()
1397 var t1 = new Task (delegate { });
1398 var t2 = new Task (delegate { t1.Start (); });
1400 var tasks = new Task[] {
1405 var t = Task.WhenAny (tasks);
1406 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1409 Assert.IsTrue (t.Wait (1000), "#2");
1410 Assert.IsNotNull (t.Result, "#3");
1414 public void WhenAnyResult_WithNull ()
1416 var tasks = new [] {
1417 Task.FromResult (2),
1422 Task.WhenAny<int> (tasks);
1424 } catch (ArgumentException) {
1429 Task.WhenAny<int> (tasks);
1431 } catch (ArgumentException) {
1435 Task.WhenAny<short> (new Task<short>[0]);
1437 } catch (ArgumentException) {
1442 public void WhenAnyResult_Start ()
1445 Task.FromResult (2),
1448 var t = Task.WhenAny<int> (tasks);
1449 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1454 } catch (InvalidOperationException) {
1458 new Task<int> (delegate { return 55; }),
1461 t = Task.WhenAny<int> (tasks);
1462 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1466 Assert.Fail ("#12");
1467 } catch (InvalidOperationException) {
1472 public void WhenAnyResult_Cancelled ()
1474 var cancelation = new CancellationTokenSource ();
1475 var tasks = new [] {
1476 new Task<double> (delegate { return 1.1; }),
1477 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1480 cancelation.Cancel ();
1482 var t = Task.WhenAny<double> (tasks);
1483 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1486 Assert.IsTrue (t.Wait (1000), "#2");
1487 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1491 public void WhenAnyResult_Faulted ()
1493 var tcs = new TaskCompletionSource<object> ();
1494 tcs.SetException (new ApplicationException ());
1496 var tcs2 = new TaskCompletionSource<object> ();
1497 tcs2.SetException (new InvalidTimeZoneException ());
1499 var cancelation = new CancellationTokenSource ();
1500 var tasks = new Task<object>[] {
1501 new Task<object> (delegate { return null; }),
1503 new Task<object> (delegate { return ""; }, cancelation.Token),
1507 cancelation.Cancel ();
1509 var t = Task.WhenAny<object> (tasks);
1510 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1513 Assert.IsTrue (t.Wait (1000), "#2");
1514 Assert.IsNull (t.Exception, "#3");
1516 Assert.IsInstanceOfType (typeof (ApplicationException), t.Result.Exception.InnerException, "#4");
1520 public void WhenAnyResult ()
1522 var t1 = new Task<byte> (delegate { return 3; });
1523 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1525 var tasks = new [] {
1530 var t = Task.WhenAny<byte> (tasks);
1531 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1534 Assert.IsTrue (t.Wait (1000), "#2");
1535 Assert.IsTrue (t.Result.Result > 1, "#3");
1539 public void ContinueWith_StateValue ()
1541 var t = Task.Factory.StartNew (l => {
1542 Assert.AreEqual (1, l, "a-1");
1545 var c = t.ContinueWith ((a, b) => {
1546 Assert.AreEqual (t, a, "c-1");
1547 Assert.AreEqual (2, b, "c-2");
1550 var d = t.ContinueWith ((a, b) => {
1551 Assert.AreEqual (t, a, "d-1");
1552 Assert.AreEqual (3, b, "d-2");
1556 Assert.IsTrue (d.Wait (1000), "#1");
1558 Assert.AreEqual (1, t.AsyncState, "#2");
1559 Assert.AreEqual (2, c.AsyncState, "#3");
1560 Assert.AreEqual (3, d.AsyncState, "#4");
1564 public void ContinueWith_StateValueGeneric ()
1566 var t = Task<int>.Factory.StartNew (l => {
1567 Assert.AreEqual (1, l, "a-1");
1571 var c = t.ContinueWith ((a, b) => {
1572 Assert.AreEqual (t, a, "c-1");
1573 Assert.AreEqual (2, b, "c-2");
1577 var d = t.ContinueWith ((a, b) => {
1578 Assert.AreEqual (t, a, "d-1");
1579 Assert.AreEqual (3, b, "d-2");
1583 Assert.IsTrue (d.Wait (1000), "#1");
1585 Assert.AreEqual (1, t.AsyncState, "#2");
1586 Assert.AreEqual (80, t.Result, "#2r");
1587 Assert.AreEqual (2, c.AsyncState, "#3");
1588 Assert.AreEqual ("c", c.Result, "#3r");
1589 Assert.AreEqual (3, d.AsyncState, "#4");
1590 Assert.AreEqual ('d', d.Result, "#3r");
1594 public void FromResult ()
1596 var t = Task.FromResult<object> (null);
1597 Assert.IsTrue (t.IsCompleted, "#1");
1598 Assert.AreEqual (null, t.Result, "#2");
1604 public void LongRunning ()
1608 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1610 Assert.IsTrue (t.Wait (100));
1611 Assert.IsTrue ((bool)is_tp, "#1");
1612 Assert.IsTrue ((bool)is_bg, "#2");
1616 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1619 Assert.IsTrue (t.Wait (100));
1620 Assert.IsFalse ((bool) is_tp, "#11");
1621 Assert.IsTrue ((bool) is_bg, "#12");
1625 public void Run_ArgumentCheck ()
1628 Task.Run (null as Action);
1630 } catch (ArgumentNullException) {
1637 bool ranOnDefaultScheduler = false;
1638 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1639 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1641 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1645 public void Run_Cancel ()
1647 var t = Task.Run (() => 1, new CancellationToken (true));
1651 } catch (AggregateException) {
1654 Assert.IsTrue (t.IsCanceled, "#2");
1658 public void Run_ExistingTaskT ()
1660 var t = new Task<int> (() => 5);
1661 var t2 = Task.Run (() => { t.Start (); return t; });
1663 Assert.IsTrue (t2.Wait (1000), "#1");
1664 Assert.AreEqual (5, t2.Result, "#2");
1668 public void Run_ExistingTask ()
1670 var t = new Task (delegate { throw new Exception ("Foo"); });
1671 var t2 = Task.Run (() => { t.Start (); return t; });
1676 } catch (Exception) {}
1678 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1682 public void DenyChildAttachTest ()
1684 var mre = new ManualResetEventSlim ();
1685 Task parent = Task.Factory.StartNew (() => {
1686 Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1687 }, TaskCreationOptions.DenyChildAttach);
1688 Assert.IsTrue (parent.Wait (500), "#1");
1692 class SynchronousScheduler : TaskScheduler
1694 protected override IEnumerable<Task> GetScheduledTasks ()
1696 throw new NotImplementedException ();
1699 protected override void QueueTask (Task task)
1701 TryExecuteTaskInline (task, false);
1704 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1706 return base.TryExecuteTask (task);
1711 public void HideSchedulerTest ()
1713 var mre = new ManualResetEventSlim ();
1714 var ranOnDefault = false;
1715 var scheduler = new SynchronousScheduler ();
1717 Task parent = Task.Factory.StartNew (() => {
1718 Task.Factory.StartNew (() => {
1719 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1722 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
1724 Assert.IsTrue (mre.Wait (1000), "#1");
1725 Assert.IsTrue (ranOnDefault, "#2");
1729 public void LazyCancelationTest ()
1731 var source = new CancellationTokenSource ();
1733 var parent = new Task (delegate {});
1734 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
1736 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
1739 Assert.IsTrue (cont.Wait (1000), "#2");
1741 } catch (AggregateException ex) {
1742 Assert.IsInstanceOfType (typeof (TaskCanceledException), ex.InnerException);