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");
336 public void WaitAll_CancelledAndTimeout ()
338 var ct = new CancellationToken (true);
339 var t1 = new Task (() => {}, ct);
340 var t2 = Task.Delay (3000);
341 Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
345 public void WaitAllExceptionThenCancelled ()
347 var cancelation = new CancellationTokenSource ();
348 var tasks = new Task[] {
349 new Task (delegate { cancelation.Cancel (); throw new ApplicationException (); }),
350 new Task (delegate { }, cancelation.Token)
356 Task.WaitAll (tasks);
358 } catch (AggregateException e) {
359 Assert.IsInstanceOfType (typeof (ApplicationException), e.InnerException, "#2");
360 var inner = (TaskCanceledException) e.InnerExceptions[1];
361 Assert.AreEqual (tasks[1], inner.Task, "#3");
364 Assert.IsTrue (tasks[0].IsCompleted, "#4");
365 Assert.IsTrue (tasks[1].IsCanceled, "#5");
369 public void WaitAll_StartedUnderWait ()
371 var task1 = new Task (delegate { });
373 ThreadPool.QueueUserWorkItem (delegate {
374 // Sleep little to let task to start and hit internal wait
379 Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
383 public void CancelBeforeStart ()
385 var src = new CancellationTokenSource ();
387 Task t = new Task (delegate { }, src.Token);
389 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
394 } catch (InvalidOperationException) {
399 public void Wait_CancelledTask ()
401 var src = new CancellationTokenSource ();
403 Task t = new Task (delegate { }, src.Token);
409 } catch (AggregateException e) {
410 var details = (TaskCanceledException) e.InnerException;
411 Assert.AreEqual (t, details.Task, "#1e");
417 } catch (AggregateException e) {
418 var details = (TaskCanceledException) e.InnerException;
419 Assert.AreEqual (t, details.Task, "#2e");
420 Assert.IsNull (details.Task.Exception, "#2e2");
425 public void Wait_Inlined ()
427 bool? previouslyQueued = null;
429 var scheduler = new MockScheduler ();
430 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
431 previouslyQueued = b;
434 var tf = new TaskFactory (scheduler);
435 var t = tf.StartNew (() => { });
438 Assert.AreEqual (true, previouslyQueued);
441 [Test, ExpectedException (typeof (InvalidOperationException))]
442 public void CreationWhileInitiallyCanceled ()
444 var token = new CancellationToken (true);
445 var task = new Task (() => { }, token);
446 Assert.AreEqual (TaskStatus.Canceled, task.Status);
451 public void ContinueWithInvalidArguments ()
453 var task = new Task (() => { });
455 task.ContinueWith (null);
457 } catch (ArgumentException) {
461 task.ContinueWith (delegate { }, null);
463 } catch (ArgumentException) {
467 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
469 } catch (ArgumentException) {
473 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
475 } catch (ArgumentException) {
480 public void ContinueWithOnAnyTestCase()
482 ParallelTestHelper.Repeat (delegate {
485 Task t = Task.Factory.StartNew(delegate { });
486 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
487 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
488 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
489 Assert.IsNull(cont.Exception, "#1");
490 Assert.IsNotNull(cont, "#2");
491 Assert.IsTrue(result, "#3");
496 public void ContinueWithOnCompletedSuccessfullyTestCase()
498 ParallelTestHelper.Repeat (delegate {
501 Task t = Task.Factory.StartNew(delegate { });
502 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
503 Assert.IsTrue (t.Wait(1000), "#4");
504 Assert.IsTrue (cont.Wait(1000), "#5");
506 Assert.IsNull(cont.Exception, "#1");
507 Assert.IsNotNull(cont, "#2");
508 Assert.IsTrue(result, "#3");
513 public void ContinueWithOnAbortedTestCase()
516 bool taskResult = false;
518 CancellationTokenSource src = new CancellationTokenSource ();
519 Task t = new Task (delegate { taskResult = true; }, src.Token);
521 Task cont = t.ContinueWith (delegate { result = true; },
522 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
526 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
527 Assert.IsTrue (cont.IsCompleted, "#1b");
528 Assert.IsTrue (result, "#1c");
533 } catch (InvalidOperationException) {
536 Assert.IsTrue (cont.Wait (1000), "#3");
538 Assert.IsFalse (taskResult, "#4");
540 Assert.IsNull (cont.Exception, "#5");
541 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
545 public void ContinueWithOnFailedTestCase()
547 ParallelTestHelper.Repeat (delegate {
550 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
551 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
553 Assert.IsTrue (cont.Wait(1000), "#0");
554 Assert.IsNotNull (t.Exception, "#1");
555 Assert.IsNotNull (cont, "#2");
556 Assert.IsTrue (result, "#3");
561 public void ContinueWithWithStart ()
563 Task t = new Task<int> (() => 1);
564 t = t.ContinueWith (l => { });
568 } catch (InvalidOperationException) {
573 public void ContinueWithChildren ()
575 ParallelTestHelper.Repeat (delegate {
578 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
580 var mre = new ManualResetEvent (false);
581 t.ContinueWith (l => {
586 Assert.IsTrue (mre.WaitOne (1000), "#1");
587 Assert.IsTrue (result, "#2");
592 public void ContinueWithDifferentOptionsAreCanceledTest ()
594 var mre = new ManualResetEventSlim ();
595 var task = Task.Factory.StartNew (() => mre.Wait (200));
596 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
597 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
598 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
601 contSuccess.Wait (100);
603 Assert.IsTrue (contSuccess.IsCompleted);
604 Assert.IsTrue (contFailed.IsCompleted);
605 Assert.IsTrue (contCanceled.IsCompleted);
606 Assert.IsFalse (contSuccess.IsCanceled);
607 Assert.IsTrue (contFailed.IsCanceled);
608 Assert.IsTrue (contCanceled.IsCanceled);
612 public void MultipleTasks()
614 ParallelTestHelper.Repeat (delegate {
615 bool r1 = false, r2 = false, r3 = false;
617 Task t1 = Task.Factory.StartNew(delegate {
620 Task t2 = Task.Factory.StartNew(delegate {
623 Task t3 = Task.Factory.StartNew(delegate {
631 Assert.IsTrue(r1, "#1");
632 Assert.IsTrue(r2, "#2");
633 Assert.IsTrue(r3, "#3");
638 public void WaitChildTestCase()
640 ParallelTestHelper.Repeat (delegate {
641 bool r1 = false, r2 = false, r3 = false;
642 var mre = new ManualResetEventSlim (false);
643 var mreStart = new ManualResetEventSlim (false);
645 Task t = Task.Factory.StartNew(delegate {
646 Task.Factory.StartNew(delegate {
649 }, TaskCreationOptions.AttachedToParent);
650 Task.Factory.StartNew(delegate {
652 }, TaskCreationOptions.AttachedToParent);
653 Task.Factory.StartNew(delegate {
655 }, TaskCreationOptions.AttachedToParent);
660 Assert.IsFalse (t.Wait (10), "#0a");
662 Assert.IsTrue (t.Wait (500), "#0b");
663 Assert.IsTrue(r2, "#1");
664 Assert.IsTrue(r3, "#2");
665 Assert.IsTrue(r1, "#3");
666 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
671 public void WaitChildWithContinuationAttachedTest ()
674 var task = new Task(() =>
676 Task.Factory.StartNew(() => {
678 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
681 }, TaskContinuationOptions.AttachedToParent);
685 Assert.IsTrue (result);
689 public void WaitChildWithContinuationNotAttachedTest ()
691 var task = new Task(() =>
693 Task.Factory.StartNew(() => {
695 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
700 Assert.IsTrue (task.Wait(400));
704 public void WaitChildWithNesting ()
707 var t = Task.Factory.StartNew (() => {
708 Task.Factory.StartNew (() => {
709 Task.Factory.StartNew (() => {
712 }, TaskCreationOptions.AttachedToParent);
713 }, TaskCreationOptions.AttachedToParent);
716 Assert.IsTrue (result);
720 public void DoubleWaitTest ()
722 ParallelTestHelper.Repeat (delegate {
723 var evt = new ManualResetEventSlim ();
724 var t = Task.Factory.StartNew (() => evt.Wait (5000));
725 var cntd = new CountdownEvent (2);
726 var cntd2 = new CountdownEvent (2);
728 bool r1 = false, r2 = false;
729 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); });
730 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); });
732 Assert.IsTrue (cntd.Wait (2000), "#1");
734 Assert.IsTrue (cntd2.Wait (2000), "#2");
735 Assert.IsTrue (r1, "r1");
736 Assert.IsTrue (r2, "r2");
741 public void DoubleTimeoutedWaitTest ()
743 var evt = new ManualResetEventSlim ();
744 var t = new Task (delegate { });
745 var cntd = new CountdownEvent (2);
747 bool r1 = false, r2 = false;
748 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
749 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
757 public void RunSynchronously ()
760 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
761 t.RunSynchronously ();
763 Assert.AreEqual (1, val, "#1");
765 t = new Task (() => { Thread.Sleep (0); val = 2; });
767 bool? previouslyQueued = null;
769 var scheduler = new MockScheduler ();
770 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
771 previouslyQueued = b;
774 t.RunSynchronously (scheduler);
776 Assert.AreEqual (2, val, "#2");
777 Assert.AreEqual (false, previouslyQueued, "#2a");
781 public void RunSynchronouslyArgumentChecks ()
783 Task t = new Task (() => { });
785 t.RunSynchronously (null);
787 } catch (ArgumentNullException) {
792 public void RunSynchronouslyWithAttachedChildren ()
795 var t = new Task (() => {
796 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
798 t.RunSynchronously ();
799 Assert.IsTrue (result);
803 public void UnobservedExceptionOnFinalizerThreadTest ()
805 bool wasCalled = false;
806 TaskScheduler.UnobservedTaskException += (o, args) => {
810 var inner = new ApplicationException ();
811 Task.Factory.StartNew (() => { throw inner; });
815 GC.WaitForPendingFinalizers ();
817 Assert.IsTrue (wasCalled);
820 [Test, ExpectedException (typeof (InvalidOperationException))]
821 public void StartFinishedTaskTest ()
823 var t = Task.Factory.StartNew (delegate () { });
830 public void Start_NullArgument ()
832 var t = Task.Factory.StartNew (delegate () { });
836 } catch (ArgumentNullException) {
840 [Test, ExpectedException (typeof (InvalidOperationException))]
841 public void DisposeUnstartedTest ()
843 var t = new Task (() => { });
848 public void ThrowingUnrelatedCanceledExceptionTest ()
850 Task t = new Task (() => {
851 throw new TaskCanceledException ();
854 t.RunSynchronously ();
855 Assert.IsTrue (t.IsFaulted);
856 Assert.IsFalse (t.IsCanceled);
860 public void CanceledContinuationExecuteSynchronouslyTest ()
862 var source = new CancellationTokenSource();
863 var token = source.Token;
864 var evt = new ManualResetEventSlim ();
868 var task = Task.Factory.StartNew (() => evt.Wait (100));
869 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
876 } catch (Exception ex) {
880 Assert.IsTrue (task.IsCompleted);
881 Assert.IsTrue (cont.IsCanceled);
882 Assert.IsFalse (result);
883 Assert.IsTrue (thrown);
887 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
889 Task innerTask = null;
890 var testTask = new Task (() =>
892 innerTask = new Task (() =>
894 throw new InvalidOperationException ();
895 }, TaskCreationOptions.AttachedToParent);
896 innerTask.RunSynchronously ();
898 testTask.RunSynchronously ();
900 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
901 Assert.IsNotNull (innerTask);
902 Assert.IsTrue (innerTask.IsFaulted);
903 Assert.IsNotNull (testTask.Exception);
904 Assert.IsTrue (testTask.IsFaulted);
905 Assert.IsNotNull (innerTask.Exception);
909 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
911 var continuationRan = false;
912 var testTask = new Task (() =>
914 var task = new Task (() =>
916 throw new InvalidOperationException();
917 }, TaskCreationOptions.AttachedToParent);
918 task.RunSynchronously ();
920 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
921 testTask.RunSynchronously ();
922 onErrorTask.Wait (100);
923 Assert.IsTrue (continuationRan);
927 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
929 var continuationRan = false;
930 var testTask = new Task (() =>
932 var task = new Task (() =>
934 throw new InvalidOperationException();
935 }, TaskCreationOptions.AttachedToParent);
936 task.RunSynchronously();
938 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
939 testTask.RunSynchronously ();
940 Assert.IsTrue (onErrorTask.IsCompleted);
941 Assert.IsFalse (onErrorTask.IsFaulted);
942 Assert.IsFalse (continuationRan);
946 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
948 var continuationRan = false;
949 AggregateException e = null;
950 var testTask = new Task (() =>
952 var child1 = new Task (() =>
954 var child2 = new Task (() =>
956 throw new InvalidOperationException();
957 }, TaskCreationOptions.AttachedToParent);
958 child2.RunSynchronously ();
959 }, TaskCreationOptions.AttachedToParent);
961 child1.RunSynchronously();
962 e = child1.Exception;
963 child1.Exception.Handle (ex => true);
965 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
966 testTask.RunSynchronously ();
967 onErrorTask.Wait (100);
968 Assert.IsNotNull (e);
969 Assert.IsTrue (continuationRan);
973 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
975 string result = "Failed";
976 var testTask = new Task (() =>
978 var child = new Task<string> (() =>
981 }, TaskCreationOptions.AttachedToParent);
982 child.RunSynchronously ();
983 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
985 testTask.RunSynchronously ();
987 Assert.AreEqual ("Success", result);
991 public void InlineNotTrashingParentRelationship ()
993 bool r1 = false, r2 = false;
994 var t = new Task (() => {
995 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
996 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
998 t.RunSynchronously ();
1006 public void Delay_Invalid ()
1010 } catch (ArgumentOutOfRangeException) {
1015 public void Delay_Start ()
1017 var t = Task.Delay (5000);
1020 } catch (InvalidOperationException) {
1025 public void Delay_Simple ()
1027 var t = Task.Delay (300);
1028 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1029 Assert.IsTrue (t.Wait (400), "#2");
1033 public void Delay_Cancelled ()
1035 var cancelation = new CancellationTokenSource ();
1037 var t = Task.Delay (5000, cancelation.Token);
1038 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1039 cancelation.Cancel ();
1043 } catch (AggregateException) {
1044 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1047 cancelation = new CancellationTokenSource ();
1048 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1049 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1050 cancelation.Cancel ();
1053 Assert.Fail ("#12");
1054 } catch (AggregateException) {
1055 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1060 public void WaitAny_WithNull ()
1062 var tasks = new [] {
1063 Task.FromResult (2),
1068 Task.WaitAny (tasks);
1070 } catch (ArgumentException) {
1075 public void WhenAll_WithNull ()
1078 Task.FromResult (2),
1083 Task.WhenAll (tasks);
1085 } catch (ArgumentException) {
1090 Task.WhenAll (tasks);
1092 } catch (ArgumentException) {
1097 public void WhenAll_Start ()
1099 Task[] tasks = new[] {
1100 Task.FromResult (2),
1103 var t = Task.WhenAll (tasks);
1104 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1109 } catch (InvalidOperationException) {
1113 new Task (delegate { }),
1116 t = Task.WhenAll (tasks);
1117 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1121 Assert.Fail ("#12");
1122 } catch (InvalidOperationException) {
1127 public void WhenAll_Cancelled ()
1129 var cancelation = new CancellationTokenSource ();
1130 var tasks = new Task[] {
1131 new Task (delegate { }),
1132 new Task (delegate { }, cancelation.Token)
1135 cancelation.Cancel ();
1137 var t = Task.WhenAll (tasks);
1138 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1142 Assert.IsTrue (t.Wait (1000), "#2");
1143 Assert.Fail ("#2a");
1144 } catch (AggregateException e) {
1145 Assert.IsInstanceOfType (typeof (TaskCanceledException), e.InnerException, "#3");
1150 public void WhenAll_Faulted ()
1152 var tcs = new TaskCompletionSource<object> ();
1153 tcs.SetException (new ApplicationException ());
1155 var tcs2 = new TaskCompletionSource<object> ();
1156 tcs2.SetException (new InvalidTimeZoneException ());
1158 var cancelation = new CancellationTokenSource ();
1159 var tasks = new Task[] {
1160 new Task (delegate { }),
1161 new Task (delegate { }, cancelation.Token),
1166 cancelation.Cancel ();
1168 var t = Task.WhenAll (tasks);
1169 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1173 Assert.IsTrue (t.Wait (1000), "#2");
1174 Assert.Fail ("#2a");
1175 } catch (AggregateException e) {
1176 Assert.IsInstanceOfType (typeof (ApplicationException), e.InnerException, "#3");
1177 Assert.IsInstanceOfType (typeof (InvalidTimeZoneException), e.InnerExceptions[1], "#4");
1182 public void WhenAll ()
1184 var t1 = new Task (delegate { });
1185 var t2 = new Task (delegate { t1.Start (); });
1187 var tasks = new Task[] {
1192 var t = Task.WhenAll (tasks);
1193 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1196 Assert.IsTrue (t.Wait (1000), "#2");
1200 public void WhenAllResult_WithNull ()
1203 Task.FromResult (2),
1208 Task.WhenAll<int> (tasks);
1210 } catch (ArgumentException) {
1215 Task.WhenAll<int> (tasks);
1217 } catch (ArgumentException) {
1222 public void WhenAllResult_Cancelled ()
1224 var cancelation = new CancellationTokenSource ();
1225 var tasks = new [] {
1226 new Task<int> (delegate { return 9; }),
1227 new Task<int> (delegate { return 1; }, cancelation.Token)
1230 cancelation.Cancel ();
1232 var t = Task.WhenAll (tasks);
1233 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1237 Assert.IsTrue (t.Wait (1000), "#2");
1238 Assert.Fail ("#2a");
1239 } catch (AggregateException e) {
1240 Assert.IsInstanceOfType (typeof (TaskCanceledException), e.InnerException, "#3");
1246 } catch (AggregateException) {
1251 public void WhenAllResult ()
1253 var t1 = new Task<string> (delegate { return "a"; });
1254 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1256 var tasks = new [] {
1261 var t = Task.WhenAll<string> (tasks);
1262 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1265 Assert.IsTrue (t.Wait (1000), "#2");
1266 Assert.AreEqual (2, t.Result.Length, "#3");
1267 Assert.AreEqual ("a", t.Result[0], "#3a");
1268 Assert.AreEqual ("b", t.Result[1], "#3b");
1272 public void WhenAllResult_Completed ()
1275 Task.FromResult (1),
1279 var t = Task.WhenAll<int> (tasks);
1280 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1281 Assert.AreEqual (2, t.Result.Length, "#2");
1282 Assert.AreEqual (1, t.Result[0], "#2a");
1283 Assert.AreEqual (2, t.Result[1], "#2b");
1287 public void WhenAny_WithNull ()
1289 var tasks = new Task[] {
1290 Task.FromResult (2),
1295 Task.WhenAny (tasks);
1297 } catch (ArgumentException) {
1302 Task.WhenAny (tasks);
1304 } catch (ArgumentException) {
1308 Task.WhenAny (new Task[0]);
1310 } catch (ArgumentException) {
1315 public void WhenAny_Start ()
1317 Task[] tasks = new[] {
1318 Task.FromResult (2),
1321 var t = Task.WhenAny (tasks);
1322 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1327 } catch (InvalidOperationException) {
1331 new Task (delegate { }),
1334 t = Task.WhenAny (tasks);
1335 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1339 Assert.Fail ("#12");
1340 } catch (InvalidOperationException) {
1345 public void WhenAny_Cancelled ()
1347 var cancelation = new CancellationTokenSource ();
1348 var tasks = new Task[] {
1349 new Task (delegate { }),
1350 new Task (delegate { }, cancelation.Token)
1353 cancelation.Cancel ();
1355 var t = Task.WhenAny (tasks);
1356 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1359 Assert.IsTrue (t.Wait (1000), "#2");
1360 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1364 public void WhenAny_Faulted ()
1366 var tcs = new TaskCompletionSource<object> ();
1367 tcs.SetException (new ApplicationException ());
1369 var tcs2 = new TaskCompletionSource<object> ();
1370 tcs2.SetException (new InvalidTimeZoneException ());
1372 var cancelation = new CancellationTokenSource ();
1373 var tasks = new Task[] {
1374 new Task (delegate { }),
1376 new Task (delegate { }, cancelation.Token),
1380 cancelation.Cancel ();
1382 var t = Task.WhenAny (tasks);
1383 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1386 Assert.IsTrue (t.Wait (1000), "#2");
1387 Assert.IsNull (t.Exception, "#3");
1389 Assert.IsInstanceOfType (typeof (ApplicationException), t.Result.Exception.InnerException, "#4");
1393 public void WhenAny ()
1395 var t1 = new Task (delegate { });
1396 var t2 = new Task (delegate { t1.Start (); });
1398 var tasks = new Task[] {
1403 var t = Task.WhenAny (tasks);
1404 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1407 Assert.IsTrue (t.Wait (1000), "#2");
1408 Assert.IsNotNull (t.Result, "#3");
1412 public void WhenAnyResult_WithNull ()
1414 var tasks = new [] {
1415 Task.FromResult (2),
1420 Task.WhenAny<int> (tasks);
1422 } catch (ArgumentException) {
1427 Task.WhenAny<int> (tasks);
1429 } catch (ArgumentException) {
1433 Task.WhenAny<short> (new Task<short>[0]);
1435 } catch (ArgumentException) {
1440 public void WhenAnyResult_Start ()
1443 Task.FromResult (2),
1446 var t = Task.WhenAny<int> (tasks);
1447 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1452 } catch (InvalidOperationException) {
1456 new Task<int> (delegate { return 55; }),
1459 t = Task.WhenAny<int> (tasks);
1460 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1464 Assert.Fail ("#12");
1465 } catch (InvalidOperationException) {
1470 public void WhenAnyResult_Cancelled ()
1472 var cancelation = new CancellationTokenSource ();
1473 var tasks = new [] {
1474 new Task<double> (delegate { return 1.1; }),
1475 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1478 cancelation.Cancel ();
1480 var t = Task.WhenAny<double> (tasks);
1481 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1484 Assert.IsTrue (t.Wait (1000), "#2");
1485 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1489 public void WhenAnyResult_Faulted ()
1491 var tcs = new TaskCompletionSource<object> ();
1492 tcs.SetException (new ApplicationException ());
1494 var tcs2 = new TaskCompletionSource<object> ();
1495 tcs2.SetException (new InvalidTimeZoneException ());
1497 var cancelation = new CancellationTokenSource ();
1498 var tasks = new Task<object>[] {
1499 new Task<object> (delegate { return null; }),
1501 new Task<object> (delegate { return ""; }, cancelation.Token),
1505 cancelation.Cancel ();
1507 var t = Task.WhenAny<object> (tasks);
1508 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1511 Assert.IsTrue (t.Wait (1000), "#2");
1512 Assert.IsNull (t.Exception, "#3");
1514 Assert.IsInstanceOfType (typeof (ApplicationException), t.Result.Exception.InnerException, "#4");
1518 public void WhenAnyResult ()
1520 var t1 = new Task<byte> (delegate { return 3; });
1521 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1523 var tasks = new [] {
1528 var t = Task.WhenAny<byte> (tasks);
1529 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1532 Assert.IsTrue (t.Wait (1000), "#2");
1533 Assert.IsTrue (t.Result.Result > 1, "#3");
1537 public void ContinueWith_StateValue ()
1539 var t = Task.Factory.StartNew (l => {
1540 Assert.AreEqual (1, l, "a-1");
1543 var c = t.ContinueWith ((a, b) => {
1544 Assert.AreEqual (t, a, "c-1");
1545 Assert.AreEqual (2, b, "c-2");
1548 var d = t.ContinueWith ((a, b) => {
1549 Assert.AreEqual (t, a, "d-1");
1550 Assert.AreEqual (3, b, "d-2");
1554 Assert.IsTrue (d.Wait (1000), "#1");
1556 Assert.AreEqual (1, t.AsyncState, "#2");
1557 Assert.AreEqual (2, c.AsyncState, "#3");
1558 Assert.AreEqual (3, d.AsyncState, "#4");
1562 public void ContinueWith_StateValueGeneric ()
1564 var t = Task<int>.Factory.StartNew (l => {
1565 Assert.AreEqual (1, l, "a-1");
1569 var c = t.ContinueWith ((a, b) => {
1570 Assert.AreEqual (t, a, "c-1");
1571 Assert.AreEqual (2, b, "c-2");
1575 var d = t.ContinueWith ((a, b) => {
1576 Assert.AreEqual (t, a, "d-1");
1577 Assert.AreEqual (3, b, "d-2");
1581 Assert.IsTrue (d.Wait (1000), "#1");
1583 Assert.AreEqual (1, t.AsyncState, "#2");
1584 Assert.AreEqual (80, t.Result, "#2r");
1585 Assert.AreEqual (2, c.AsyncState, "#3");
1586 Assert.AreEqual ("c", c.Result, "#3r");
1587 Assert.AreEqual (3, d.AsyncState, "#4");
1588 Assert.AreEqual ('d', d.Result, "#3r");
1592 public void FromResult ()
1594 var t = Task.FromResult<object> (null);
1595 Assert.IsTrue (t.IsCompleted, "#1");
1596 Assert.AreEqual (null, t.Result, "#2");
1602 public void LongRunning ()
1606 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1608 Assert.IsTrue (t.Wait (100));
1609 Assert.IsTrue ((bool)is_tp, "#1");
1610 Assert.IsTrue ((bool)is_bg, "#2");
1614 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1617 Assert.IsTrue (t.Wait (100));
1618 Assert.IsFalse ((bool) is_tp, "#11");
1619 Assert.IsTrue ((bool) is_bg, "#12");
1623 public void Run_ArgumentCheck ()
1626 Task.Run (null as Action);
1628 } catch (ArgumentNullException) {
1635 bool ranOnDefaultScheduler = false;
1636 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1637 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1639 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1643 public void Run_Cancel ()
1645 var t = Task.Run (() => 1, new CancellationToken (true));
1649 } catch (AggregateException) {
1652 Assert.IsTrue (t.IsCanceled, "#2");
1656 public void Run_ExistingTaskT ()
1658 var t = new Task<int> (() => 5);
1659 var t2 = Task.Run (() => { t.Start (); return t; });
1661 Assert.IsTrue (t2.Wait (1000), "#1");
1662 Assert.AreEqual (5, t2.Result, "#2");
1666 public void Run_ExistingTask ()
1668 var t = new Task (delegate { throw new Exception ("Foo"); });
1669 var t2 = Task.Run (() => { t.Start (); return t; });
1674 } catch (Exception) {}
1676 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");