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);
70 class NonInlineableScheduler : TaskScheduler
72 protected override IEnumerable<Task> GetScheduledTasks ()
74 throw new NotImplementedException ();
77 protected override void QueueTask (Task task)
79 if (!base.TryExecuteTask (task))
80 throw new ApplicationException ();
83 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
89 class ExceptionScheduler : TaskScheduler
91 protected override IEnumerable<Task> GetScheduledTasks ()
93 throw new ApplicationException ("1");
96 protected override void QueueTask (Task task)
98 throw new ApplicationException ("2");
101 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
103 throw new ApplicationException ("3");
108 int completionPortThreads;
116 ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
117 ThreadPool.SetMinThreads (1, 1);
119 tasks = new Task[max];
123 public void Teardown()
125 ThreadPool.SetMinThreads (workerThreads, completionPortThreads);
128 void InitWithDelegate(Action action)
130 for (int i = 0; i < max; i++) {
131 tasks[i] = Task.Factory.StartNew(action);
136 public void WaitAnyTest()
138 ParallelTestHelper.Repeat (delegate {
142 InitWithDelegate(delegate {
143 int times = Interlocked.Exchange (ref flag, 1);
145 SpinWait sw = new SpinWait ();
146 while (finished == 0) sw.SpinOnce ();
148 Interlocked.Increment (ref finished);
152 int index = Task.WaitAny(tasks, 1000);
154 Assert.AreNotEqual (-1, index, "#3");
155 Assert.AreEqual (1, flag, "#1");
156 Assert.AreEqual (1, finished, "#2");
161 public void WaitAny_Empty ()
163 Assert.AreEqual (-1, Task.WaitAny (new Task[0]));
167 public void WaitAny_Zero ()
169 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { })}, 0), "#1");
170 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { }) }, 20), "#1");
174 public void WaitAny_Cancelled ()
176 var cancelation = new CancellationTokenSource ();
177 var tasks = new Task[] {
178 new Task (delegate { }),
179 new Task (delegate { }, cancelation.Token)
182 cancelation.Cancel ();
184 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
185 Assert.IsTrue (tasks[1].IsCompleted, "#2");
186 Assert.IsTrue (tasks[1].IsCanceled, "#3");
190 public void WaitAny_CancelledWithoutExecution ()
192 var cancelation = new CancellationTokenSource ();
193 var tasks = new Task[] {
194 new Task (delegate { }),
195 new Task (delegate { })
199 var mre = new ManualResetEventSlim (false);
200 ThreadPool.QueueUserWorkItem (delegate {
201 res = Task.WaitAny (tasks, 20);
205 cancelation.Cancel ();
206 Assert.IsTrue (mre.Wait (1000), "#1");
207 Assert.AreEqual (-1, res);
211 public void WaitAny_OneException ()
213 var mre = new ManualResetEventSlim (false);
214 var tasks = new Task[] {
215 Task.Factory.StartNew (delegate { mre.Wait (1000); }),
216 Task.Factory.StartNew (delegate { throw new ApplicationException (); })
219 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
220 Assert.IsFalse (tasks[0].IsCompleted, "#2");
221 Assert.IsTrue (tasks[1].IsFaulted, "#3");
227 public void WaitAny_SingleCanceled ()
229 var src = new CancellationTokenSource ();
230 var t = Task.Factory.StartNew (() => { Thread.Sleep (200); src.Cancel (); src.Token.ThrowIfCancellationRequested (); }, src.Token);
231 Assert.AreEqual (0, Task.WaitAny (new [] { t }));
234 public void WaitAny_ManyExceptions ()
236 CountdownEvent cde = new CountdownEvent (3);
238 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
239 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
240 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
243 Assert.IsTrue (cde.Wait (1000), "#1");
246 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#2");
247 } catch (AggregateException e) {
248 Assert.AreEqual (3, e.InnerExceptions.Count, "#3");
253 public void WaitAny_ManyCanceled ()
255 var cancellation = new CancellationToken (true);
257 Task.Factory.StartNew (delegate { }, cancellation),
258 Task.Factory.StartNew (delegate { }, cancellation),
259 Task.Factory.StartNew (delegate { }, cancellation)
263 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#1");
264 } catch (AggregateException e) {
265 Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
270 public void WaitAllTest ()
272 ParallelTestHelper.Repeat (delegate {
274 InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
276 Assert.AreEqual(max, achieved, "#1");
281 public void WaitAll_ManyTasks ()
283 for (int r = 0; r < 2000; ++r) {
284 var tasks = new Task[60];
286 for (int i = 0; i < tasks.Length; i++) {
287 tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
290 Assert.IsTrue (Task.WaitAll (tasks, 5000));
295 public void WaitAll_Zero ()
297 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 0), "#0");
298 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 10), "#1");
302 public void WaitAll_WithExceptions ()
304 InitWithDelegate (delegate { throw new ApplicationException (); });
307 Task.WaitAll (tasks);
309 } catch (AggregateException e) {
310 Assert.AreEqual (6, e.InnerExceptions.Count, "#2");
313 Assert.IsNotNull (tasks[0].Exception, "#3");
317 public void WaitAll_TimeoutWithExceptionsAfter ()
319 CountdownEvent cde = new CountdownEvent (2);
320 var mre = new ManualResetEvent (false);
322 Task.Factory.StartNew (delegate { mre.WaitOne (); }),
323 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
324 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
327 Assert.IsTrue (cde.Wait (1000), "#1");
328 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
333 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
335 } catch (AggregateException e) {
336 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
341 public void WaitAll_TimeoutWithExceptionsBefore ()
343 CountdownEvent cde = new CountdownEvent (2);
344 var mre = new ManualResetEvent (false);
346 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
347 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
348 Task.Factory.StartNew (delegate { mre.WaitOne (); })
351 Assert.IsTrue (cde.Wait (1000), "#1");
352 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
357 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
359 } catch (AggregateException e) {
360 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
365 public void WaitAll_Cancelled ()
367 var cancelation = new CancellationTokenSource ();
368 var tasks = new Task[] {
369 new Task (delegate { cancelation.Cancel (); }),
370 new Task (delegate { }, cancelation.Token)
376 Task.WaitAll (tasks);
378 } catch (AggregateException e) {
379 var inner = (TaskCanceledException) e.InnerException;
380 Assert.AreEqual (tasks[1], inner.Task, "#2");
383 Assert.IsTrue (tasks[0].IsCompleted, "#3");
384 Assert.IsTrue (tasks[1].IsCanceled, "#4");
389 public void WaitAll_CancelledAndTimeout ()
391 var ct = new CancellationToken (true);
392 var t1 = new Task (() => {}, ct);
393 var t2 = Task.Delay (3000);
394 Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
399 public void WaitAllExceptionThenCancelled ()
401 var cancelation = new CancellationTokenSource ();
402 var tasks = new Task[] {
403 new Task (delegate { cancelation.Cancel (); throw new ApplicationException (); }),
404 new Task (delegate { }, cancelation.Token)
410 Task.WaitAll (tasks);
412 } catch (AggregateException e) {
413 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#2");
414 var inner = (TaskCanceledException) e.InnerExceptions[1];
415 Assert.AreEqual (tasks[1], inner.Task, "#3");
418 Assert.IsTrue (tasks[0].IsCompleted, "#4");
419 Assert.IsTrue (tasks[1].IsCanceled, "#5");
423 public void WaitAll_StartedUnderWait ()
425 var task1 = new Task (delegate { });
427 ThreadPool.QueueUserWorkItem (delegate {
428 // Sleep little to let task to start and hit internal wait
433 Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
437 public void CancelBeforeStart ()
439 var src = new CancellationTokenSource ();
441 Task t = new Task (delegate { }, src.Token);
443 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
448 } catch (InvalidOperationException) {
453 public void Wait_CancelledTask ()
455 var src = new CancellationTokenSource ();
457 Task t = new Task (delegate { }, src.Token);
463 } catch (AggregateException e) {
464 var details = (TaskCanceledException) e.InnerException;
465 Assert.AreEqual (t, details.Task, "#1e");
471 } catch (AggregateException e) {
472 var details = (TaskCanceledException) e.InnerException;
473 Assert.AreEqual (t, details.Task, "#2e");
474 Assert.IsNull (details.Task.Exception, "#2e2");
479 public void Wait_Inlined ()
481 bool? previouslyQueued = null;
483 var scheduler = new MockScheduler ();
484 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
485 previouslyQueued = b;
488 var tf = new TaskFactory (scheduler);
489 var t = tf.StartNew (() => { });
492 Assert.AreEqual (true, previouslyQueued);
496 public void CreationWhileInitiallyCanceled ()
498 var token = new CancellationToken (true);
499 var task = new Task (() => { }, token);
504 } catch (InvalidOperationException) {
510 } catch (AggregateException e) {
511 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
514 Assert.IsTrue (task.IsCanceled, "#4");
518 public void ContinueWithInvalidArguments ()
520 var task = new Task (() => { });
522 task.ContinueWith (null);
524 } catch (ArgumentNullException e) {
528 task.ContinueWith (delegate { }, null);
530 } catch (ArgumentNullException e) {
534 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
536 } catch (ArgumentOutOfRangeException) {
540 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
542 } catch (ArgumentOutOfRangeException) {
547 public void ContinueWithOnAnyTestCase()
549 ParallelTestHelper.Repeat (delegate {
552 Task t = Task.Factory.StartNew(delegate { });
553 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
554 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
555 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
556 Assert.IsNull(cont.Exception, "#1");
557 Assert.IsNotNull(cont, "#2");
558 Assert.IsTrue(result, "#3");
563 public void ContinueWithOnCompletedSuccessfullyTestCase()
565 ParallelTestHelper.Repeat (delegate {
568 Task t = Task.Factory.StartNew(delegate { });
569 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
570 Assert.IsTrue (t.Wait(1000), "#4");
571 Assert.IsTrue (cont.Wait(1000), "#5");
573 Assert.IsNull(cont.Exception, "#1");
574 Assert.IsNotNull(cont, "#2");
575 Assert.IsTrue(result, "#3");
580 public void ContinueWithOnAbortedTestCase()
583 bool taskResult = false;
585 CancellationTokenSource src = new CancellationTokenSource ();
586 Task t = new Task (delegate { taskResult = true; }, src.Token);
588 Task cont = t.ContinueWith (delegate { result = true; },
589 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
593 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
594 Assert.IsTrue (cont.IsCompleted, "#1b");
595 Assert.IsTrue (result, "#1c");
600 } catch (InvalidOperationException) {
603 Assert.IsTrue (cont.Wait (1000), "#3");
605 Assert.IsFalse (taskResult, "#4");
607 Assert.IsNull (cont.Exception, "#5");
608 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
612 public void ContinueWithOnFailedTestCase()
614 ParallelTestHelper.Repeat (delegate {
617 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
618 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
620 Assert.IsTrue (cont.Wait(1000), "#0");
621 Assert.IsNotNull (t.Exception, "#1");
622 Assert.IsNotNull (cont, "#2");
623 Assert.IsTrue (result, "#3");
628 public void ContinueWithWithStart ()
630 Task t = new Task<int> (() => 1);
631 t = t.ContinueWith (l => { });
635 } catch (InvalidOperationException) {
640 public void ContinueWithChildren ()
642 ParallelTestHelper.Repeat (delegate {
645 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
647 var mre = new ManualResetEvent (false);
648 t.ContinueWith (l => {
653 Assert.IsTrue (mre.WaitOne (1000), "#1");
654 Assert.IsTrue (result, "#2");
659 public void ContinueWithDifferentOptionsAreCanceledTest ()
661 var mre = new ManualResetEventSlim ();
662 var task = Task.Factory.StartNew (() => mre.Wait (200));
663 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
664 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
665 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
668 contSuccess.Wait (100);
670 Assert.IsTrue (contSuccess.IsCompleted);
671 Assert.IsTrue (contFailed.IsCompleted);
672 Assert.IsTrue (contCanceled.IsCompleted);
673 Assert.IsFalse (contSuccess.IsCanceled);
674 Assert.IsTrue (contFailed.IsCanceled);
675 Assert.IsTrue (contCanceled.IsCanceled);
679 public void MultipleTasks()
681 ParallelTestHelper.Repeat (delegate {
682 bool r1 = false, r2 = false, r3 = false;
684 Task t1 = Task.Factory.StartNew(delegate {
687 Task t2 = Task.Factory.StartNew(delegate {
690 Task t3 = Task.Factory.StartNew(delegate {
698 Assert.IsTrue(r1, "#1");
699 Assert.IsTrue(r2, "#2");
700 Assert.IsTrue(r3, "#3");
705 public void WaitChildTestCase()
707 ParallelTestHelper.Repeat (delegate {
708 bool r1 = false, r2 = false, r3 = false;
709 var mre = new ManualResetEventSlim (false);
710 var mreStart = new ManualResetEventSlim (false);
712 Task t = Task.Factory.StartNew(delegate {
713 Task.Factory.StartNew(delegate {
716 }, TaskCreationOptions.AttachedToParent);
717 Task.Factory.StartNew(delegate {
719 }, TaskCreationOptions.AttachedToParent);
720 Task.Factory.StartNew(delegate {
722 }, TaskCreationOptions.AttachedToParent);
727 Assert.IsFalse (t.Wait (10), "#0a");
729 Assert.IsTrue (t.Wait (500), "#0b");
730 Assert.IsTrue(r2, "#1");
731 Assert.IsTrue(r3, "#2");
732 Assert.IsTrue(r1, "#3");
733 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
740 public void WaitingForChildrenToComplete ()
743 var mre = new ManualResetEvent (false);
745 parent_wfc = Task.Factory.StartNew (() => {
746 nested = Task.Factory.StartNew (() => {
747 Assert.IsTrue (mre.WaitOne (4000), "parent_wfc needs to be set first");
748 Assert.IsFalse (parent_wfc.Wait (10), "#1a");
749 Assert.AreEqual (TaskStatus.WaitingForChildrenToComplete, parent_wfc.Status, "#1b");
750 }, TaskCreationOptions.AttachedToParent).ContinueWith (l => {
751 Assert.IsTrue (parent_wfc.Wait (2000), "#2a");
752 Assert.AreEqual (TaskStatus.RanToCompletion, parent_wfc.Status, "#2b");
753 }, TaskContinuationOptions.ExecuteSynchronously);
757 Assert.IsTrue (parent_wfc.Wait (2000), "#3");
758 Assert.IsTrue (nested.Wait (2000), "#4");
762 public void WaitChildWithContinuationAttachedTest ()
765 var task = new Task(() =>
767 Task.Factory.StartNew(() => {
769 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
772 }, TaskContinuationOptions.AttachedToParent);
776 Assert.IsTrue (result);
780 public void WaitChildWithContinuationNotAttachedTest ()
782 var task = new Task(() =>
784 Task.Factory.StartNew(() => {
786 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
791 Assert.IsTrue (task.Wait(400));
795 public void WaitChildWithNesting ()
798 var t = Task.Factory.StartNew (() => {
799 Task.Factory.StartNew (() => {
800 Task.Factory.StartNew (() => {
803 }, TaskCreationOptions.AttachedToParent);
804 }, TaskCreationOptions.AttachedToParent);
806 Assert.IsTrue (t.Wait (4000), "#1");
807 Assert.IsTrue (result, "#2");
811 public void DoubleWaitTest ()
813 ParallelTestHelper.Repeat (delegate {
814 var evt = new ManualResetEventSlim ();
815 var monitor = new object ();
817 var t = Task.Factory.StartNew (delegate {
818 var r = evt.Wait (5000);
821 Monitor.Pulse (monitor);
823 return r ? 1 : 10; //1 -> ok, 10 -> evt wait failed
825 var cntd = new CountdownEvent (2);
826 var cntd2 = new CountdownEvent (2);
829 ThreadPool.QueueUserWorkItem (delegate {
832 r1 = 20; // 20 -> task wait failed
833 else if (t.Result != 1)
834 r1 = 30 + t.Result; // 30 -> task result is bad
840 Monitor.Pulse (monitor);
843 ThreadPool.QueueUserWorkItem (delegate {
846 r2 = 40; // 40 -> task wait failed
847 else if (t.Result != 1)
848 r2 = 50 + t.Result; // 50 -> task result is bad
855 Monitor.Pulse (monitor);
858 Assert.IsTrue (cntd.Wait (2000), "#1");
860 Assert.IsTrue (cntd2.Wait (2000), "#2");
861 Assert.AreEqual (2, r1, "r1");
862 Assert.AreEqual (3, r2, "r2");
864 // Wait for everything to finish to avoid overloading the tpool
870 Monitor.Wait (monitor);
877 public void DoubleTimeoutedWaitTest ()
879 var evt = new ManualResetEventSlim ();
880 var t = new Task (delegate { });
881 var cntd = new CountdownEvent (2);
883 bool r1 = false, r2 = false;
884 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
885 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
893 public void RunSynchronously ()
896 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
897 t.RunSynchronously ();
899 Assert.AreEqual (1, val, "#1");
901 t = new Task (() => { Thread.Sleep (0); val = 2; });
903 bool? previouslyQueued = null;
905 var scheduler = new MockScheduler ();
906 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
907 previouslyQueued = b;
910 t.RunSynchronously (scheduler);
912 Assert.AreEqual (2, val, "#2");
913 Assert.AreEqual (false, previouslyQueued, "#2a");
917 public void RunSynchronouslyArgumentChecks ()
919 Task t = new Task (() => { });
921 t.RunSynchronously (null);
923 } catch (ArgumentNullException) {
928 public void RunSynchronously_SchedulerException ()
930 var scheduler = new MockScheduler ();
931 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
932 throw new ApplicationException ();
935 Task t = new Task (() => { });
937 t.RunSynchronously (scheduler);
939 } catch (Exception e) {
940 Assert.AreEqual (t.Exception.InnerException, e);
945 public void RunSynchronouslyWithAttachedChildren ()
948 var t = new Task (() => {
949 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
951 t.RunSynchronously ();
952 Assert.IsTrue (result);
956 public void RunSynchronouslyOnContinuation ()
958 Task t = new Task<int> (() => 1);
959 t = t.ContinueWith (l => { });
961 t.RunSynchronously ();
963 } catch (InvalidOperationException) {
968 public void UnobservedExceptionOnFinalizerThreadTest ()
970 bool wasCalled = false;
971 TaskScheduler.UnobservedTaskException += (o, args) => {
975 var inner = new ApplicationException ();
976 Thread t = new Thread (delegate () {
977 Task.Factory.StartNew (() => { throw inner; });
984 GC.WaitForPendingFinalizers ();
986 Assert.IsTrue (wasCalled);
989 [Test, ExpectedException (typeof (InvalidOperationException))]
990 public void StartFinishedTaskTest ()
992 var t = Task.Factory.StartNew (delegate () { });
999 public void Start_NullArgument ()
1001 var t = new Task (() => { });
1005 } catch (ArgumentNullException) {
1009 [Test, ExpectedException (typeof (InvalidOperationException))]
1010 public void DisposeUnstartedTest ()
1012 var t = new Task (() => { });
1017 public void ThrowingUnrelatedCanceledExceptionTest ()
1019 Task t = new Task (() => {
1020 throw new TaskCanceledException ();
1023 t.RunSynchronously ();
1024 Assert.IsTrue (t.IsFaulted);
1025 Assert.IsFalse (t.IsCanceled);
1029 public void CanceledContinuationExecuteSynchronouslyTest ()
1031 var source = new CancellationTokenSource();
1032 var token = source.Token;
1033 var evt = new ManualResetEventSlim ();
1034 bool result = false;
1035 bool thrown = false;
1037 var task = Task.Factory.StartNew (() => evt.Wait (100));
1038 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
1045 } catch (Exception ex) {
1049 Assert.IsTrue (task.IsCompleted);
1050 Assert.IsTrue (cont.IsCanceled);
1051 Assert.IsFalse (result);
1052 Assert.IsTrue (thrown);
1056 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
1058 Task innerTask = null;
1059 var testTask = new Task (() =>
1061 innerTask = new Task (() =>
1063 throw new InvalidOperationException ();
1064 }, TaskCreationOptions.AttachedToParent);
1065 innerTask.RunSynchronously ();
1067 testTask.RunSynchronously ();
1069 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
1070 Assert.IsNotNull (innerTask);
1071 Assert.IsTrue (innerTask.IsFaulted);
1072 Assert.IsNotNull (testTask.Exception);
1073 Assert.IsTrue (testTask.IsFaulted);
1074 Assert.IsNotNull (innerTask.Exception);
1078 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
1080 var continuationRan = false;
1081 var testTask = new Task (() =>
1083 var task = new Task (() =>
1085 throw new InvalidOperationException();
1086 }, TaskCreationOptions.AttachedToParent);
1087 task.RunSynchronously ();
1089 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1090 testTask.RunSynchronously ();
1091 onErrorTask.Wait (100);
1092 Assert.IsTrue (continuationRan);
1096 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
1098 var continuationRan = false;
1099 var testTask = new Task (() =>
1101 var task = new Task (() =>
1103 throw new InvalidOperationException();
1104 }, TaskCreationOptions.AttachedToParent);
1105 task.RunSynchronously();
1107 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
1108 testTask.RunSynchronously ();
1109 Assert.IsTrue (onErrorTask.IsCompleted);
1110 Assert.IsFalse (onErrorTask.IsFaulted);
1111 Assert.IsFalse (continuationRan);
1115 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
1117 var continuationRan = false;
1118 AggregateException e = null;
1119 var testTask = new Task (() =>
1121 var child1 = new Task (() =>
1123 var child2 = new Task (() =>
1125 throw new InvalidOperationException();
1126 }, TaskCreationOptions.AttachedToParent);
1127 child2.RunSynchronously ();
1128 }, TaskCreationOptions.AttachedToParent);
1130 child1.RunSynchronously();
1131 e = child1.Exception;
1132 child1.Exception.Handle (ex => true);
1134 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1135 testTask.RunSynchronously ();
1136 onErrorTask.Wait (100);
1137 Assert.IsNotNull (e);
1138 Assert.IsTrue (continuationRan);
1142 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1144 string result = "Failed";
1145 var testTask = new Task (() =>
1147 var child = new Task<string> (() =>
1150 }, TaskCreationOptions.AttachedToParent);
1151 child.RunSynchronously ();
1152 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1154 testTask.RunSynchronously ();
1156 Assert.AreEqual ("Success", result);
1160 public void InlineNotTrashingParentRelationship ()
1162 bool r1 = false, r2 = false;
1163 var t = new Task (() => {
1164 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1165 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1167 t.RunSynchronously ();
1174 public void AsyncWaitHandleSet ()
1176 var task = new TaskFactory ().StartNew (() => { });
1177 var ar = (IAsyncResult)task;
1178 Assert.IsFalse (ar.CompletedSynchronously, "#1");
1179 Assert.IsTrue (ar.AsyncWaitHandle.WaitOne (5000), "#2");
1183 public void StartOnBrokenScheduler ()
1185 var t = new Task (delegate { });
1188 t.Start (new ExceptionScheduler ());
1190 } catch (TaskSchedulerException e) {
1191 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1192 Assert.AreSame (e, t.Exception.InnerException, "#3");
1193 Assert.IsTrue (e.InnerException is ApplicationException, "#4");
1199 public void ContinuationOnBrokenScheduler ()
1201 var s = new ExceptionScheduler ();
1202 Task t = new Task(delegate {});
1204 var t2 = t.ContinueWith (delegate {
1205 }, TaskContinuationOptions.ExecuteSynchronously, s);
1207 var t3 = t.ContinueWith (delegate {
1208 }, TaskContinuationOptions.ExecuteSynchronously, s);
1213 Assert.IsTrue (t3.Wait (2000), "#0");
1215 } catch (AggregateException e) {
1218 Assert.AreEqual (TaskStatus.Faulted, t2.Status, "#2");
1219 Assert.AreEqual (TaskStatus.Faulted, t3.Status, "#3");
1223 public void Delay_Invalid ()
1227 } catch (ArgumentOutOfRangeException) {
1232 public void Delay_Start ()
1234 var t = Task.Delay (5000);
1237 } catch (InvalidOperationException) {
1242 public void Delay_Simple ()
1244 var t = Task.Delay (300);
1245 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1246 Assert.IsTrue (t.Wait (400), "#2");
1250 public void Delay_Cancelled ()
1252 var cancelation = new CancellationTokenSource ();
1254 var t = Task.Delay (5000, cancelation.Token);
1255 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1256 cancelation.Cancel ();
1260 } catch (AggregateException) {
1261 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1264 cancelation = new CancellationTokenSource ();
1265 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1266 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1267 cancelation.Cancel ();
1270 Assert.Fail ("#12");
1271 } catch (AggregateException) {
1272 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1277 public void Delay_TimeManagement ()
1279 var delay1 = Task.Delay(50);
1280 var delay2 = Task.Delay(25);
1281 Assert.IsTrue (Task.WhenAny(new[] { delay1, delay2 }).Wait (1000));
1282 Assert.AreEqual (TaskStatus.RanToCompletion, delay2.Status);
1286 public void WaitAny_WithNull ()
1288 var tasks = new [] {
1289 Task.FromResult (2),
1294 Task.WaitAny (tasks);
1296 } catch (ArgumentException) {
1301 public void WhenAll_Empty ()
1303 var tasks = new Task[0];
1305 Task t = Task.WhenAll(tasks);
1307 Assert.IsTrue(t.Wait(1000), "#1");
1311 public void WhenAll_WithNull ()
1314 Task.FromResult (2),
1319 Task.WhenAll (tasks);
1321 } catch (ArgumentException) {
1326 Task.WhenAll (tasks);
1328 } catch (ArgumentException) {
1333 public void WhenAll_Start ()
1335 Task[] tasks = new[] {
1336 Task.FromResult (2),
1339 var t = Task.WhenAll (tasks);
1340 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1345 } catch (InvalidOperationException) {
1349 new Task (delegate { }),
1352 t = Task.WhenAll (tasks);
1353 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1357 Assert.Fail ("#12");
1358 } catch (InvalidOperationException) {
1363 public void WhenAll_Cancelled ()
1365 var cancelation = new CancellationTokenSource ();
1366 var tasks = new Task[] {
1367 new Task (delegate { }),
1368 new Task (delegate { }, cancelation.Token)
1371 cancelation.Cancel ();
1373 var t = Task.WhenAll (tasks);
1374 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1378 Assert.IsTrue (t.Wait (1000), "#2");
1379 Assert.Fail ("#2a");
1380 } catch (AggregateException e) {
1381 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1386 public void WhenAll_Faulted ()
1388 var tcs = new TaskCompletionSource<object> ();
1389 tcs.SetException (new ApplicationException ());
1391 var tcs2 = new TaskCompletionSource<object> ();
1392 tcs2.SetException (new InvalidTimeZoneException ());
1394 var cancelation = new CancellationTokenSource ();
1395 var tasks = new Task[] {
1396 new Task (delegate { }),
1397 new Task (delegate { }, cancelation.Token),
1402 cancelation.Cancel ();
1404 var t = Task.WhenAll (tasks);
1405 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1409 Assert.IsTrue (t.Wait (1000), "#2");
1410 Assert.Fail ("#2a");
1411 } catch (AggregateException e) {
1412 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1413 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1418 public void WhenAll ()
1420 var t1 = new Task (delegate { });
1421 var t2 = new Task (delegate { t1.Start (); });
1423 var tasks = new Task[] {
1428 var t = Task.WhenAll (tasks);
1429 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1432 Assert.IsTrue (t.Wait (1000), "#2");
1436 public void WhenAllResult_Empty ()
1438 var tasks = new Task<int>[0];
1440 Task<int[]> t = Task.WhenAll(tasks);
1442 Assert.IsTrue(t.Wait(1000), "#1");
1443 Assert.IsNotNull(t.Result, "#2");
1444 Assert.AreEqual(t.Result.Length, 0, "#3");
1448 public void WhenAllResult_WithNull ()
1451 Task.FromResult (2),
1456 Task.WhenAll<int> (tasks);
1458 } catch (ArgumentException) {
1463 Task.WhenAll<int> (tasks);
1465 } catch (ArgumentException) {
1470 public void WhenAllResult_Cancelled ()
1472 var cancelation = new CancellationTokenSource ();
1473 var tasks = new [] {
1474 new Task<int> (delegate { return 9; }),
1475 new Task<int> (delegate { return 1; }, cancelation.Token)
1478 cancelation.Cancel ();
1480 var t = Task.WhenAll (tasks);
1481 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1485 Assert.IsTrue (t.Wait (1000), "#2");
1486 Assert.Fail ("#2a");
1487 } catch (AggregateException e) {
1488 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1494 } catch (AggregateException) {
1499 public void WhenAllResult ()
1501 var t1 = new Task<string> (delegate { return "a"; });
1502 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1504 var tasks = new [] {
1509 var t = Task.WhenAll<string> (tasks);
1510 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1513 Assert.IsTrue (t.Wait (1000), "#2");
1514 Assert.AreEqual (2, t.Result.Length, "#3");
1515 Assert.AreEqual ("a", t.Result[0], "#3a");
1516 Assert.AreEqual ("b", t.Result[1], "#3b");
1520 public void WhenAllResult_Completed ()
1523 Task.FromResult (1),
1527 var t = Task.WhenAll<int> (tasks);
1528 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1529 Assert.AreEqual (2, t.Result.Length, "#2");
1530 Assert.AreEqual (1, t.Result[0], "#2a");
1531 Assert.AreEqual (2, t.Result[1], "#2b");
1535 public void WhenAny_WithNull ()
1537 var tasks = new Task[] {
1538 Task.FromResult (2),
1543 Task.WhenAny (tasks);
1545 } catch (ArgumentException) {
1550 Task.WhenAny (tasks);
1552 } catch (ArgumentException) {
1556 Task.WhenAny (new Task[0]);
1558 } catch (ArgumentException) {
1563 public void WhenAny_Start ()
1565 Task[] tasks = new[] {
1566 Task.FromResult (2),
1569 var t = Task.WhenAny (tasks);
1570 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1575 } catch (InvalidOperationException) {
1579 new Task (delegate { }),
1582 t = Task.WhenAny (tasks);
1583 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1587 Assert.Fail ("#12");
1588 } catch (InvalidOperationException) {
1593 public void WhenAny_Cancelled ()
1595 var cancelation = new CancellationTokenSource ();
1596 var tasks = new Task[] {
1597 new Task (delegate { }),
1598 new Task (delegate { }, cancelation.Token)
1601 cancelation.Cancel ();
1603 var t = Task.WhenAny (tasks);
1604 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1607 Assert.IsTrue (t.Wait (1000), "#2");
1608 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1612 public void WhenAny_Faulted ()
1614 var tcs = new TaskCompletionSource<object> ();
1615 tcs.SetException (new ApplicationException ());
1617 var tcs2 = new TaskCompletionSource<object> ();
1618 tcs2.SetException (new InvalidTimeZoneException ());
1620 var cancelation = new CancellationTokenSource ();
1621 var tasks = new Task[] {
1622 new Task (delegate { }),
1624 new Task (delegate { }, cancelation.Token),
1628 cancelation.Cancel ();
1630 var t = Task.WhenAny (tasks);
1631 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1634 Assert.IsTrue (t.Wait (1000), "#2");
1635 Assert.IsNull (t.Exception, "#3");
1637 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1641 public void WhenAny ()
1643 var t1 = new Task (delegate { });
1644 var t2 = new Task (delegate { t1.Start (); });
1646 var tasks = new Task[] {
1651 var t = Task.WhenAny (tasks);
1652 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1655 Assert.IsTrue (t.Wait (1000), "#2");
1656 Assert.IsNotNull (t.Result, "#3");
1660 public void WhenAnyResult_WithNull ()
1662 var tasks = new [] {
1663 Task.FromResult (2),
1668 Task.WhenAny<int> (tasks);
1670 } catch (ArgumentException) {
1675 Task.WhenAny<int> (tasks);
1677 } catch (ArgumentException) {
1681 Task.WhenAny<short> (new Task<short>[0]);
1683 } catch (ArgumentException) {
1688 public void WhenAnyResult_Start ()
1691 Task.FromResult (2),
1694 var t = Task.WhenAny<int> (tasks);
1695 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1700 } catch (InvalidOperationException) {
1704 new Task<int> (delegate { return 55; }),
1707 t = Task.WhenAny<int> (tasks);
1708 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1712 Assert.Fail ("#12");
1713 } catch (InvalidOperationException) {
1718 public void WhenAnyResult_Cancelled ()
1720 var cancelation = new CancellationTokenSource ();
1721 var tasks = new [] {
1722 new Task<double> (delegate { return 1.1; }),
1723 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1726 cancelation.Cancel ();
1728 var t = Task.WhenAny<double> (tasks);
1729 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1732 Assert.IsTrue (t.Wait (1000), "#2");
1733 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1737 public void WhenAnyResult_Faulted ()
1739 var tcs = new TaskCompletionSource<object> ();
1740 tcs.SetException (new ApplicationException ());
1742 var tcs2 = new TaskCompletionSource<object> ();
1743 tcs2.SetException (new InvalidTimeZoneException ());
1745 var cancelation = new CancellationTokenSource ();
1746 var tasks = new Task<object>[] {
1747 new Task<object> (delegate { return null; }),
1749 new Task<object> (delegate { return ""; }, cancelation.Token),
1753 cancelation.Cancel ();
1755 var t = Task.WhenAny<object> (tasks);
1756 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1759 Assert.IsTrue (t.Wait (1000), "#2");
1760 Assert.IsNull (t.Exception, "#3");
1762 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1766 public void WhenAnyResult ()
1768 var t1 = new Task<byte> (delegate { return 3; });
1769 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1771 var tasks = new [] {
1776 var t = Task.WhenAny<byte> (tasks);
1777 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1780 Assert.IsTrue (t.Wait (1000), "#2");
1781 Assert.IsTrue (t.Result.Result > 1, "#3");
1785 public void ContinueWith_StateValue ()
1787 var t = Task.Factory.StartNew (l => {
1788 Assert.AreEqual (1, l, "a-1");
1791 var c = t.ContinueWith ((a, b) => {
1792 Assert.AreEqual (t, a, "c-1");
1793 Assert.AreEqual (2, b, "c-2");
1796 var d = t.ContinueWith ((a, b) => {
1797 Assert.AreEqual (t, a, "d-1");
1798 Assert.AreEqual (3, b, "d-2");
1802 Assert.IsTrue (d.Wait (1000), "#1");
1804 Assert.AreEqual (1, t.AsyncState, "#2");
1805 Assert.AreEqual (2, c.AsyncState, "#3");
1806 Assert.AreEqual (3, d.AsyncState, "#4");
1810 public void ContinueWith_StateValueGeneric ()
1812 var t = Task<int>.Factory.StartNew (l => {
1813 Assert.AreEqual (1, l, "a-1");
1817 var c = t.ContinueWith ((a, b) => {
1818 Assert.AreEqual (t, a, "c-1");
1819 Assert.AreEqual (2, b, "c-2");
1823 var d = t.ContinueWith ((a, b) => {
1824 Assert.AreEqual (t, a, "d-1");
1825 Assert.AreEqual (3, b, "d-2");
1829 Assert.IsTrue (d.Wait (1000), "#1");
1831 Assert.AreEqual (1, t.AsyncState, "#2");
1832 Assert.AreEqual (80, t.Result, "#2r");
1833 Assert.AreEqual (2, c.AsyncState, "#3");
1834 Assert.AreEqual ("c", c.Result, "#3r");
1835 Assert.AreEqual (3, d.AsyncState, "#4");
1836 Assert.AreEqual ('d', d.Result, "#3r");
1840 public void ContinueWith_CustomScheduleRejected ()
1842 var scheduler = new NonInlineableScheduler ();
1843 var t = Task.Factory.StartNew (delegate { }).
1844 ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
1846 Assert.IsTrue (t.Wait (5000));
1850 public void FromResult ()
1852 var t = Task.FromResult<object> (null);
1853 Assert.IsTrue (t.IsCompleted, "#1");
1854 Assert.AreEqual (null, t.Result, "#2");
1860 public void LongRunning ()
1864 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1867 Assert.IsTrue ((bool)is_tp, "#1");
1868 Assert.IsTrue ((bool)is_bg, "#2");
1872 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1875 Assert.IsFalse ((bool) is_tp, "#11");
1876 Assert.IsTrue ((bool) is_bg, "#12");
1880 public void Run_ArgumentCheck ()
1883 Task.Run (null as Action);
1885 } catch (ArgumentNullException) {
1892 bool ranOnDefaultScheduler = false;
1893 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1894 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1896 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1900 public void Run_Cancel ()
1902 var t = Task.Run (() => 1, new CancellationToken (true));
1906 } catch (AggregateException) {
1909 Assert.IsTrue (t.IsCanceled, "#2");
1913 public void Run_ExistingTaskT ()
1915 var t = new Task<int> (() => 5);
1916 var t2 = Task.Run (() => { t.Start (); return t; });
1918 Assert.IsTrue (t2.Wait (1000), "#1");
1919 Assert.AreEqual (5, t2.Result, "#2");
1923 public void Run_ExistingTask ()
1925 var t = new Task (delegate { throw new Exception ("Foo"); });
1926 var t2 = Task.Run (() => { t.Start (); return t; });
1931 } catch (Exception) {}
1933 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1937 public void DenyChildAttachTest ()
1939 var mre = new ManualResetEventSlim ();
1941 Task parent = Task.Factory.StartNew (() => {
1942 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1943 }, TaskCreationOptions.DenyChildAttach);
1944 Assert.IsTrue (parent.Wait (1000), "#1");
1946 Assert.IsTrue (nested.Wait (2000), "#2");
1949 class SynchronousScheduler : TaskScheduler
1951 protected override IEnumerable<Task> GetScheduledTasks ()
1953 throw new NotImplementedException ();
1956 protected override void QueueTask (Task task)
1958 TryExecuteTaskInline (task, false);
1961 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1963 return base.TryExecuteTask (task);
1968 public void HideSchedulerTest ()
1970 var mre = new ManualResetEventSlim ();
1971 var ranOnDefault = false;
1972 var scheduler = new SynchronousScheduler ();
1974 Task parent = Task.Factory.StartNew (() => {
1975 Task.Factory.StartNew (() => {
1976 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1979 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
1981 Assert.IsTrue (mre.Wait (1000), "#1");
1982 Assert.IsTrue (ranOnDefault, "#2");
1986 public void LazyCancelationTest ()
1988 var source = new CancellationTokenSource ();
1990 var parent = new Task (delegate {});
1991 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
1993 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
1996 Assert.IsTrue (cont.Wait (1000), "#2");
1998 } catch (AggregateException ex) {
1999 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
2004 public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
2007 var child = Task.Factory.StartNew (() => {
2008 inner = Task.Run (() => {
2009 throw new ApplicationException ();
2010 }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
2014 var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
2015 Assert.IsTrue (t.Wait (5000), "#1");
2016 Assert.AreEqual (1, counter, "#2");
2017 Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
2018 Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
2022 [Category("NotWorking")]
2023 public void TaskContinuationChainLeak()
2025 // Start cranking out tasks, starting each new task upon completion of and from inside the prior task.
2027 var tester = new TaskContinuationChainLeakTester ();
2029 tester.TasksPilledUp.WaitOne ();
2031 // Head task should be out of scope by now. Manually run the GC and expect that it gets collected.
2034 GC.WaitForPendingFinalizers ();
2037 // It's important that we do the asserting while the task recursion is still going, since that is the
2038 // crux of the problem scenario.
2046 class TaskContinuationChainLeakTester
2048 volatile bool m_bStop;
2050 ManualResetEvent mre = new ManualResetEvent (false);
2051 WeakReference<Task> headTaskWeakRef;
2053 public ManualResetEvent TasksPilledUp {
2061 headTaskWeakRef = new WeakReference<Task> (StartNewTask ());
2064 public Task StartNewTask ()
2069 if (++counter == 50)
2072 return Task.Factory.StartNew (DummyWorker).ContinueWith (task => StartNewTask ());
2080 public void Verify ()
2083 Assert.IsFalse (headTaskWeakRef.TryGetTarget (out task));