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);
495 [Test, ExpectedException (typeof (InvalidOperationException))]
496 public void CreationWhileInitiallyCanceled ()
498 var token = new CancellationToken (true);
499 var task = new Task (() => { }, token);
500 Assert.AreEqual (TaskStatus.Canceled, task.Status);
505 public void ContinueWithInvalidArguments ()
507 var task = new Task (() => { });
509 task.ContinueWith (null);
511 } catch (ArgumentException) {
515 task.ContinueWith (delegate { }, null);
517 } catch (ArgumentException) {
521 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
523 } catch (ArgumentException) {
527 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
529 } catch (ArgumentException) {
534 public void ContinueWithOnAnyTestCase()
536 ParallelTestHelper.Repeat (delegate {
539 Task t = Task.Factory.StartNew(delegate { });
540 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
541 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
542 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
543 Assert.IsNull(cont.Exception, "#1");
544 Assert.IsNotNull(cont, "#2");
545 Assert.IsTrue(result, "#3");
550 public void ContinueWithOnCompletedSuccessfullyTestCase()
552 ParallelTestHelper.Repeat (delegate {
555 Task t = Task.Factory.StartNew(delegate { });
556 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
557 Assert.IsTrue (t.Wait(1000), "#4");
558 Assert.IsTrue (cont.Wait(1000), "#5");
560 Assert.IsNull(cont.Exception, "#1");
561 Assert.IsNotNull(cont, "#2");
562 Assert.IsTrue(result, "#3");
567 public void ContinueWithOnAbortedTestCase()
570 bool taskResult = false;
572 CancellationTokenSource src = new CancellationTokenSource ();
573 Task t = new Task (delegate { taskResult = true; }, src.Token);
575 Task cont = t.ContinueWith (delegate { result = true; },
576 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
580 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
581 Assert.IsTrue (cont.IsCompleted, "#1b");
582 Assert.IsTrue (result, "#1c");
587 } catch (InvalidOperationException) {
590 Assert.IsTrue (cont.Wait (1000), "#3");
592 Assert.IsFalse (taskResult, "#4");
594 Assert.IsNull (cont.Exception, "#5");
595 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
599 public void ContinueWithOnFailedTestCase()
601 ParallelTestHelper.Repeat (delegate {
604 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
605 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
607 Assert.IsTrue (cont.Wait(1000), "#0");
608 Assert.IsNotNull (t.Exception, "#1");
609 Assert.IsNotNull (cont, "#2");
610 Assert.IsTrue (result, "#3");
615 public void ContinueWithWithStart ()
617 Task t = new Task<int> (() => 1);
618 t = t.ContinueWith (l => { });
622 } catch (InvalidOperationException) {
627 public void ContinueWithChildren ()
629 ParallelTestHelper.Repeat (delegate {
632 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
634 var mre = new ManualResetEvent (false);
635 t.ContinueWith (l => {
640 Assert.IsTrue (mre.WaitOne (1000), "#1");
641 Assert.IsTrue (result, "#2");
646 public void ContinueWithDifferentOptionsAreCanceledTest ()
648 var mre = new ManualResetEventSlim ();
649 var task = Task.Factory.StartNew (() => mre.Wait (200));
650 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
651 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
652 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
655 contSuccess.Wait (100);
657 Assert.IsTrue (contSuccess.IsCompleted);
658 Assert.IsTrue (contFailed.IsCompleted);
659 Assert.IsTrue (contCanceled.IsCompleted);
660 Assert.IsFalse (contSuccess.IsCanceled);
661 Assert.IsTrue (contFailed.IsCanceled);
662 Assert.IsTrue (contCanceled.IsCanceled);
666 public void MultipleTasks()
668 ParallelTestHelper.Repeat (delegate {
669 bool r1 = false, r2 = false, r3 = false;
671 Task t1 = Task.Factory.StartNew(delegate {
674 Task t2 = Task.Factory.StartNew(delegate {
677 Task t3 = Task.Factory.StartNew(delegate {
685 Assert.IsTrue(r1, "#1");
686 Assert.IsTrue(r2, "#2");
687 Assert.IsTrue(r3, "#3");
692 public void WaitChildTestCase()
694 ParallelTestHelper.Repeat (delegate {
695 bool r1 = false, r2 = false, r3 = false;
696 var mre = new ManualResetEventSlim (false);
697 var mreStart = new ManualResetEventSlim (false);
699 Task t = Task.Factory.StartNew(delegate {
700 Task.Factory.StartNew(delegate {
703 }, TaskCreationOptions.AttachedToParent);
704 Task.Factory.StartNew(delegate {
706 }, TaskCreationOptions.AttachedToParent);
707 Task.Factory.StartNew(delegate {
709 }, TaskCreationOptions.AttachedToParent);
714 Assert.IsFalse (t.Wait (10), "#0a");
716 Assert.IsTrue (t.Wait (500), "#0b");
717 Assert.IsTrue(r2, "#1");
718 Assert.IsTrue(r3, "#2");
719 Assert.IsTrue(r1, "#3");
720 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
727 public void WaitingForChildrenToComplete ()
730 var mre = new ManualResetEvent (false);
732 parent_wfc = Task.Factory.StartNew (() => {
733 nested = Task.Factory.StartNew (() => {
734 Assert.IsTrue (mre.WaitOne (4000), "parent_wfc needs to be set first");
735 Assert.IsFalse (parent_wfc.Wait (10), "#1a");
736 Assert.AreEqual (TaskStatus.WaitingForChildrenToComplete, parent_wfc.Status, "#1b");
737 }, TaskCreationOptions.AttachedToParent).ContinueWith (l => {
738 Assert.IsTrue (parent_wfc.Wait (2000), "#2a");
739 Assert.AreEqual (TaskStatus.RanToCompletion, parent_wfc.Status, "#2b");
740 }, TaskContinuationOptions.ExecuteSynchronously);
744 Assert.IsTrue (parent_wfc.Wait (2000), "#3");
745 Assert.IsTrue (nested.Wait (2000), "#4");
749 public void WaitChildWithContinuationAttachedTest ()
752 var task = new Task(() =>
754 Task.Factory.StartNew(() => {
756 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
759 }, TaskContinuationOptions.AttachedToParent);
763 Assert.IsTrue (result);
767 public void WaitChildWithContinuationNotAttachedTest ()
769 var task = new Task(() =>
771 Task.Factory.StartNew(() => {
773 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
778 Assert.IsTrue (task.Wait(400));
782 public void WaitChildWithNesting ()
785 var t = Task.Factory.StartNew (() => {
786 Task.Factory.StartNew (() => {
787 Task.Factory.StartNew (() => {
790 }, TaskCreationOptions.AttachedToParent);
791 }, TaskCreationOptions.AttachedToParent);
793 Assert.IsTrue (t.Wait (4000), "#1");
794 Assert.IsTrue (result, "#2");
798 public void DoubleWaitTest ()
800 ParallelTestHelper.Repeat (delegate {
801 var evt = new ManualResetEventSlim ();
802 var monitor = new object ();
804 var t = Task.Factory.StartNew (delegate {
805 var r = evt.Wait (5000);
808 Monitor.Pulse (monitor);
810 return r ? 1 : 10; //1 -> ok, 10 -> evt wait failed
812 var cntd = new CountdownEvent (2);
813 var cntd2 = new CountdownEvent (2);
816 ThreadPool.QueueUserWorkItem (delegate {
819 r1 = 20; // 20 -> task wait failed
820 else if (t.Result != 1)
821 r1 = 30 + t.Result; // 30 -> task result is bad
827 Monitor.Pulse (monitor);
830 ThreadPool.QueueUserWorkItem (delegate {
833 r2 = 40; // 40 -> task wait failed
834 else if (t.Result != 1)
835 r2 = 50 + t.Result; // 50 -> task result is bad
842 Monitor.Pulse (monitor);
845 Assert.IsTrue (cntd.Wait (2000), "#1");
847 Assert.IsTrue (cntd2.Wait (2000), "#2");
848 Assert.AreEqual (2, r1, "r1");
849 Assert.AreEqual (3, r2, "r2");
851 // Wait for everything to finish to avoid overloading the tpool
857 Monitor.Wait (monitor);
864 public void DoubleTimeoutedWaitTest ()
866 var evt = new ManualResetEventSlim ();
867 var t = new Task (delegate { });
868 var cntd = new CountdownEvent (2);
870 bool r1 = false, r2 = false;
871 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
872 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
880 public void RunSynchronously ()
883 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
884 t.RunSynchronously ();
886 Assert.AreEqual (1, val, "#1");
888 t = new Task (() => { Thread.Sleep (0); val = 2; });
890 bool? previouslyQueued = null;
892 var scheduler = new MockScheduler ();
893 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
894 previouslyQueued = b;
897 t.RunSynchronously (scheduler);
899 Assert.AreEqual (2, val, "#2");
900 Assert.AreEqual (false, previouslyQueued, "#2a");
904 public void RunSynchronouslyArgumentChecks ()
906 Task t = new Task (() => { });
908 t.RunSynchronously (null);
910 } catch (ArgumentNullException) {
915 public void RunSynchronously_SchedulerException ()
917 var scheduler = new MockScheduler ();
918 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
919 throw new ApplicationException ();
922 Task t = new Task (() => { });
924 t.RunSynchronously (scheduler);
926 } catch (Exception e) {
927 Assert.AreEqual (t.Exception.InnerException, e);
932 public void RunSynchronouslyWithAttachedChildren ()
935 var t = new Task (() => {
936 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
938 t.RunSynchronously ();
939 Assert.IsTrue (result);
943 public void RunSynchronouslyOnContinuation ()
945 Task t = new Task<int> (() => 1);
946 t = t.ContinueWith (l => { });
948 t.RunSynchronously ();
950 } catch (InvalidOperationException) {
955 public void UnobservedExceptionOnFinalizerThreadTest ()
957 bool wasCalled = false;
958 TaskScheduler.UnobservedTaskException += (o, args) => {
962 var inner = new ApplicationException ();
963 Thread t = new Thread (delegate () {
964 Task.Factory.StartNew (() => { throw inner; });
971 GC.WaitForPendingFinalizers ();
973 Assert.IsTrue (wasCalled);
976 [Test, ExpectedException (typeof (InvalidOperationException))]
977 public void StartFinishedTaskTest ()
979 var t = Task.Factory.StartNew (delegate () { });
986 public void Start_NullArgument ()
988 var t = Task.Factory.StartNew (delegate () { });
992 } catch (ArgumentNullException) {
996 [Test, ExpectedException (typeof (InvalidOperationException))]
997 public void DisposeUnstartedTest ()
999 var t = new Task (() => { });
1004 public void ThrowingUnrelatedCanceledExceptionTest ()
1006 Task t = new Task (() => {
1007 throw new TaskCanceledException ();
1010 t.RunSynchronously ();
1011 Assert.IsTrue (t.IsFaulted);
1012 Assert.IsFalse (t.IsCanceled);
1016 public void CanceledContinuationExecuteSynchronouslyTest ()
1018 var source = new CancellationTokenSource();
1019 var token = source.Token;
1020 var evt = new ManualResetEventSlim ();
1021 bool result = false;
1022 bool thrown = false;
1024 var task = Task.Factory.StartNew (() => evt.Wait (100));
1025 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
1032 } catch (Exception ex) {
1036 Assert.IsTrue (task.IsCompleted);
1037 Assert.IsTrue (cont.IsCanceled);
1038 Assert.IsFalse (result);
1039 Assert.IsTrue (thrown);
1043 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
1045 Task innerTask = null;
1046 var testTask = new Task (() =>
1048 innerTask = new Task (() =>
1050 throw new InvalidOperationException ();
1051 }, TaskCreationOptions.AttachedToParent);
1052 innerTask.RunSynchronously ();
1054 testTask.RunSynchronously ();
1056 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
1057 Assert.IsNotNull (innerTask);
1058 Assert.IsTrue (innerTask.IsFaulted);
1059 Assert.IsNotNull (testTask.Exception);
1060 Assert.IsTrue (testTask.IsFaulted);
1061 Assert.IsNotNull (innerTask.Exception);
1065 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
1067 var continuationRan = false;
1068 var testTask = new Task (() =>
1070 var task = new Task (() =>
1072 throw new InvalidOperationException();
1073 }, TaskCreationOptions.AttachedToParent);
1074 task.RunSynchronously ();
1076 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1077 testTask.RunSynchronously ();
1078 onErrorTask.Wait (100);
1079 Assert.IsTrue (continuationRan);
1083 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
1085 var continuationRan = false;
1086 var testTask = new Task (() =>
1088 var task = new Task (() =>
1090 throw new InvalidOperationException();
1091 }, TaskCreationOptions.AttachedToParent);
1092 task.RunSynchronously();
1094 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
1095 testTask.RunSynchronously ();
1096 Assert.IsTrue (onErrorTask.IsCompleted);
1097 Assert.IsFalse (onErrorTask.IsFaulted);
1098 Assert.IsFalse (continuationRan);
1102 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
1104 var continuationRan = false;
1105 AggregateException e = null;
1106 var testTask = new Task (() =>
1108 var child1 = new Task (() =>
1110 var child2 = new Task (() =>
1112 throw new InvalidOperationException();
1113 }, TaskCreationOptions.AttachedToParent);
1114 child2.RunSynchronously ();
1115 }, TaskCreationOptions.AttachedToParent);
1117 child1.RunSynchronously();
1118 e = child1.Exception;
1119 child1.Exception.Handle (ex => true);
1121 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1122 testTask.RunSynchronously ();
1123 onErrorTask.Wait (100);
1124 Assert.IsNotNull (e);
1125 Assert.IsTrue (continuationRan);
1129 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1131 string result = "Failed";
1132 var testTask = new Task (() =>
1134 var child = new Task<string> (() =>
1137 }, TaskCreationOptions.AttachedToParent);
1138 child.RunSynchronously ();
1139 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1141 testTask.RunSynchronously ();
1143 Assert.AreEqual ("Success", result);
1147 public void InlineNotTrashingParentRelationship ()
1149 bool r1 = false, r2 = false;
1150 var t = new Task (() => {
1151 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1152 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1154 t.RunSynchronously ();
1161 public void AsyncWaitHandleSet ()
1163 var task = new TaskFactory ().StartNew (() => { });
1164 var ar = (IAsyncResult)task;
1165 Assert.IsFalse (ar.CompletedSynchronously, "#1");
1166 Assert.IsTrue (ar.AsyncWaitHandle.WaitOne (5000), "#2");
1170 public void StartOnBrokenScheduler ()
1172 var t = new Task (delegate { });
1175 t.Start (new ExceptionScheduler ());
1177 } catch (TaskSchedulerException e) {
1178 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1179 Assert.AreSame (e, t.Exception.InnerException, "#3");
1180 Assert.IsTrue (e.InnerException is ApplicationException, "#4");
1186 public void ContinuationOnBrokenScheduler ()
1188 var s = new ExceptionScheduler ();
1189 Task t = new Task(delegate {});
1191 var t2 = t.ContinueWith (delegate {
1192 }, TaskContinuationOptions.ExecuteSynchronously, s);
1194 var t3 = t.ContinueWith (delegate {
1195 }, TaskContinuationOptions.ExecuteSynchronously, s);
1200 Assert.IsTrue (t3.Wait (2000), "#0");
1202 } catch (AggregateException e) {
1205 Assert.AreEqual (TaskStatus.Faulted, t2.Status, "#2");
1206 Assert.AreEqual (TaskStatus.Faulted, t3.Status, "#3");
1210 public void Delay_Invalid ()
1214 } catch (ArgumentOutOfRangeException) {
1219 public void Delay_Start ()
1221 var t = Task.Delay (5000);
1224 } catch (InvalidOperationException) {
1229 public void Delay_Simple ()
1231 var t = Task.Delay (300);
1232 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1233 Assert.IsTrue (t.Wait (400), "#2");
1237 public void Delay_Cancelled ()
1239 var cancelation = new CancellationTokenSource ();
1241 var t = Task.Delay (5000, cancelation.Token);
1242 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1243 cancelation.Cancel ();
1247 } catch (AggregateException) {
1248 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1251 cancelation = new CancellationTokenSource ();
1252 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1253 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1254 cancelation.Cancel ();
1257 Assert.Fail ("#12");
1258 } catch (AggregateException) {
1259 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1264 public void Delay_TimeManagement ()
1266 var delay1 = Task.Delay(50);
1267 var delay2 = Task.Delay(25);
1268 Assert.IsTrue (Task.WhenAny(new[] { delay1, delay2 }).Wait (1000));
1269 Assert.AreEqual (TaskStatus.RanToCompletion, delay2.Status);
1273 public void WaitAny_WithNull ()
1275 var tasks = new [] {
1276 Task.FromResult (2),
1281 Task.WaitAny (tasks);
1283 } catch (ArgumentException) {
1288 public void WhenAll_Empty ()
1290 var tasks = new Task[0];
1292 Task t = Task.WhenAll(tasks);
1294 Assert.IsTrue(t.Wait(1000), "#1");
1298 public void WhenAll_WithNull ()
1301 Task.FromResult (2),
1306 Task.WhenAll (tasks);
1308 } catch (ArgumentException) {
1313 Task.WhenAll (tasks);
1315 } catch (ArgumentException) {
1320 public void WhenAll_Start ()
1322 Task[] tasks = new[] {
1323 Task.FromResult (2),
1326 var t = Task.WhenAll (tasks);
1327 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1332 } catch (InvalidOperationException) {
1336 new Task (delegate { }),
1339 t = Task.WhenAll (tasks);
1340 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1344 Assert.Fail ("#12");
1345 } catch (InvalidOperationException) {
1350 public void WhenAll_Cancelled ()
1352 var cancelation = new CancellationTokenSource ();
1353 var tasks = new Task[] {
1354 new Task (delegate { }),
1355 new Task (delegate { }, cancelation.Token)
1358 cancelation.Cancel ();
1360 var t = Task.WhenAll (tasks);
1361 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1365 Assert.IsTrue (t.Wait (1000), "#2");
1366 Assert.Fail ("#2a");
1367 } catch (AggregateException e) {
1368 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1373 public void WhenAll_Faulted ()
1375 var tcs = new TaskCompletionSource<object> ();
1376 tcs.SetException (new ApplicationException ());
1378 var tcs2 = new TaskCompletionSource<object> ();
1379 tcs2.SetException (new InvalidTimeZoneException ());
1381 var cancelation = new CancellationTokenSource ();
1382 var tasks = new Task[] {
1383 new Task (delegate { }),
1384 new Task (delegate { }, cancelation.Token),
1389 cancelation.Cancel ();
1391 var t = Task.WhenAll (tasks);
1392 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1396 Assert.IsTrue (t.Wait (1000), "#2");
1397 Assert.Fail ("#2a");
1398 } catch (AggregateException e) {
1399 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1400 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1405 public void WhenAll ()
1407 var t1 = new Task (delegate { });
1408 var t2 = new Task (delegate { t1.Start (); });
1410 var tasks = new Task[] {
1415 var t = Task.WhenAll (tasks);
1416 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1419 Assert.IsTrue (t.Wait (1000), "#2");
1423 public void WhenAllResult_Empty ()
1425 var tasks = new Task<int>[0];
1427 Task<int[]> t = Task.WhenAll(tasks);
1429 Assert.IsTrue(t.Wait(1000), "#1");
1430 Assert.IsNotNull(t.Result, "#2");
1431 Assert.AreEqual(t.Result.Length, 0, "#3");
1435 public void WhenAllResult_WithNull ()
1438 Task.FromResult (2),
1443 Task.WhenAll<int> (tasks);
1445 } catch (ArgumentException) {
1450 Task.WhenAll<int> (tasks);
1452 } catch (ArgumentException) {
1457 public void WhenAllResult_Cancelled ()
1459 var cancelation = new CancellationTokenSource ();
1460 var tasks = new [] {
1461 new Task<int> (delegate { return 9; }),
1462 new Task<int> (delegate { return 1; }, cancelation.Token)
1465 cancelation.Cancel ();
1467 var t = Task.WhenAll (tasks);
1468 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1472 Assert.IsTrue (t.Wait (1000), "#2");
1473 Assert.Fail ("#2a");
1474 } catch (AggregateException e) {
1475 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1481 } catch (AggregateException) {
1486 public void WhenAllResult ()
1488 var t1 = new Task<string> (delegate { return "a"; });
1489 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1491 var tasks = new [] {
1496 var t = Task.WhenAll<string> (tasks);
1497 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1500 Assert.IsTrue (t.Wait (1000), "#2");
1501 Assert.AreEqual (2, t.Result.Length, "#3");
1502 Assert.AreEqual ("a", t.Result[0], "#3a");
1503 Assert.AreEqual ("b", t.Result[1], "#3b");
1507 public void WhenAllResult_Completed ()
1510 Task.FromResult (1),
1514 var t = Task.WhenAll<int> (tasks);
1515 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1516 Assert.AreEqual (2, t.Result.Length, "#2");
1517 Assert.AreEqual (1, t.Result[0], "#2a");
1518 Assert.AreEqual (2, t.Result[1], "#2b");
1522 public void WhenAny_WithNull ()
1524 var tasks = new Task[] {
1525 Task.FromResult (2),
1530 Task.WhenAny (tasks);
1532 } catch (ArgumentException) {
1537 Task.WhenAny (tasks);
1539 } catch (ArgumentException) {
1543 Task.WhenAny (new Task[0]);
1545 } catch (ArgumentException) {
1550 public void WhenAny_Start ()
1552 Task[] tasks = new[] {
1553 Task.FromResult (2),
1556 var t = Task.WhenAny (tasks);
1557 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1562 } catch (InvalidOperationException) {
1566 new Task (delegate { }),
1569 t = Task.WhenAny (tasks);
1570 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1574 Assert.Fail ("#12");
1575 } catch (InvalidOperationException) {
1580 public void WhenAny_Cancelled ()
1582 var cancelation = new CancellationTokenSource ();
1583 var tasks = new Task[] {
1584 new Task (delegate { }),
1585 new Task (delegate { }, cancelation.Token)
1588 cancelation.Cancel ();
1590 var t = Task.WhenAny (tasks);
1591 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1594 Assert.IsTrue (t.Wait (1000), "#2");
1595 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1599 public void WhenAny_Faulted ()
1601 var tcs = new TaskCompletionSource<object> ();
1602 tcs.SetException (new ApplicationException ());
1604 var tcs2 = new TaskCompletionSource<object> ();
1605 tcs2.SetException (new InvalidTimeZoneException ());
1607 var cancelation = new CancellationTokenSource ();
1608 var tasks = new Task[] {
1609 new Task (delegate { }),
1611 new Task (delegate { }, cancelation.Token),
1615 cancelation.Cancel ();
1617 var t = Task.WhenAny (tasks);
1618 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1621 Assert.IsTrue (t.Wait (1000), "#2");
1622 Assert.IsNull (t.Exception, "#3");
1624 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1628 public void WhenAny ()
1630 var t1 = new Task (delegate { });
1631 var t2 = new Task (delegate { t1.Start (); });
1633 var tasks = new Task[] {
1638 var t = Task.WhenAny (tasks);
1639 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1642 Assert.IsTrue (t.Wait (1000), "#2");
1643 Assert.IsNotNull (t.Result, "#3");
1647 public void WhenAnyResult_WithNull ()
1649 var tasks = new [] {
1650 Task.FromResult (2),
1655 Task.WhenAny<int> (tasks);
1657 } catch (ArgumentException) {
1662 Task.WhenAny<int> (tasks);
1664 } catch (ArgumentException) {
1668 Task.WhenAny<short> (new Task<short>[0]);
1670 } catch (ArgumentException) {
1675 public void WhenAnyResult_Start ()
1678 Task.FromResult (2),
1681 var t = Task.WhenAny<int> (tasks);
1682 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1687 } catch (InvalidOperationException) {
1691 new Task<int> (delegate { return 55; }),
1694 t = Task.WhenAny<int> (tasks);
1695 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1699 Assert.Fail ("#12");
1700 } catch (InvalidOperationException) {
1705 public void WhenAnyResult_Cancelled ()
1707 var cancelation = new CancellationTokenSource ();
1708 var tasks = new [] {
1709 new Task<double> (delegate { return 1.1; }),
1710 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1713 cancelation.Cancel ();
1715 var t = Task.WhenAny<double> (tasks);
1716 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1719 Assert.IsTrue (t.Wait (1000), "#2");
1720 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1724 public void WhenAnyResult_Faulted ()
1726 var tcs = new TaskCompletionSource<object> ();
1727 tcs.SetException (new ApplicationException ());
1729 var tcs2 = new TaskCompletionSource<object> ();
1730 tcs2.SetException (new InvalidTimeZoneException ());
1732 var cancelation = new CancellationTokenSource ();
1733 var tasks = new Task<object>[] {
1734 new Task<object> (delegate { return null; }),
1736 new Task<object> (delegate { return ""; }, cancelation.Token),
1740 cancelation.Cancel ();
1742 var t = Task.WhenAny<object> (tasks);
1743 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1746 Assert.IsTrue (t.Wait (1000), "#2");
1747 Assert.IsNull (t.Exception, "#3");
1749 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1753 public void WhenAnyResult ()
1755 var t1 = new Task<byte> (delegate { return 3; });
1756 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1758 var tasks = new [] {
1763 var t = Task.WhenAny<byte> (tasks);
1764 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1767 Assert.IsTrue (t.Wait (1000), "#2");
1768 Assert.IsTrue (t.Result.Result > 1, "#3");
1772 public void ContinueWith_StateValue ()
1774 var t = Task.Factory.StartNew (l => {
1775 Assert.AreEqual (1, l, "a-1");
1778 var c = t.ContinueWith ((a, b) => {
1779 Assert.AreEqual (t, a, "c-1");
1780 Assert.AreEqual (2, b, "c-2");
1783 var d = t.ContinueWith ((a, b) => {
1784 Assert.AreEqual (t, a, "d-1");
1785 Assert.AreEqual (3, b, "d-2");
1789 Assert.IsTrue (d.Wait (1000), "#1");
1791 Assert.AreEqual (1, t.AsyncState, "#2");
1792 Assert.AreEqual (2, c.AsyncState, "#3");
1793 Assert.AreEqual (3, d.AsyncState, "#4");
1797 public void ContinueWith_StateValueGeneric ()
1799 var t = Task<int>.Factory.StartNew (l => {
1800 Assert.AreEqual (1, l, "a-1");
1804 var c = t.ContinueWith ((a, b) => {
1805 Assert.AreEqual (t, a, "c-1");
1806 Assert.AreEqual (2, b, "c-2");
1810 var d = t.ContinueWith ((a, b) => {
1811 Assert.AreEqual (t, a, "d-1");
1812 Assert.AreEqual (3, b, "d-2");
1816 Assert.IsTrue (d.Wait (1000), "#1");
1818 Assert.AreEqual (1, t.AsyncState, "#2");
1819 Assert.AreEqual (80, t.Result, "#2r");
1820 Assert.AreEqual (2, c.AsyncState, "#3");
1821 Assert.AreEqual ("c", c.Result, "#3r");
1822 Assert.AreEqual (3, d.AsyncState, "#4");
1823 Assert.AreEqual ('d', d.Result, "#3r");
1827 public void ContinueWith_CustomScheduleRejected ()
1829 var scheduler = new NonInlineableScheduler ();
1830 var t = Task.Factory.StartNew (delegate { }).
1831 ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
1833 Assert.IsTrue (t.Wait (5000));
1837 public void FromResult ()
1839 var t = Task.FromResult<object> (null);
1840 Assert.IsTrue (t.IsCompleted, "#1");
1841 Assert.AreEqual (null, t.Result, "#2");
1847 public void LongRunning ()
1851 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1853 Assert.IsTrue (t.Wait (100));
1854 Assert.IsTrue ((bool)is_tp, "#1");
1855 Assert.IsTrue ((bool)is_bg, "#2");
1859 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1862 Assert.IsTrue (t.Wait (100));
1863 Assert.IsFalse ((bool) is_tp, "#11");
1864 Assert.IsTrue ((bool) is_bg, "#12");
1868 public void Run_ArgumentCheck ()
1871 Task.Run (null as Action);
1873 } catch (ArgumentNullException) {
1880 bool ranOnDefaultScheduler = false;
1881 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1882 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1884 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1888 public void Run_Cancel ()
1890 var t = Task.Run (() => 1, new CancellationToken (true));
1894 } catch (AggregateException) {
1897 Assert.IsTrue (t.IsCanceled, "#2");
1901 public void Run_ExistingTaskT ()
1903 var t = new Task<int> (() => 5);
1904 var t2 = Task.Run (() => { t.Start (); return t; });
1906 Assert.IsTrue (t2.Wait (1000), "#1");
1907 Assert.AreEqual (5, t2.Result, "#2");
1911 public void Run_ExistingTask ()
1913 var t = new Task (delegate { throw new Exception ("Foo"); });
1914 var t2 = Task.Run (() => { t.Start (); return t; });
1919 } catch (Exception) {}
1921 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1925 public void DenyChildAttachTest ()
1927 var mre = new ManualResetEventSlim ();
1929 Task parent = Task.Factory.StartNew (() => {
1930 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1931 }, TaskCreationOptions.DenyChildAttach);
1932 Assert.IsTrue (parent.Wait (1000), "#1");
1934 Assert.IsTrue (nested.Wait (2000), "#2");
1937 class SynchronousScheduler : TaskScheduler
1939 protected override IEnumerable<Task> GetScheduledTasks ()
1941 throw new NotImplementedException ();
1944 protected override void QueueTask (Task task)
1946 TryExecuteTaskInline (task, false);
1949 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1951 return base.TryExecuteTask (task);
1956 public void HideSchedulerTest ()
1958 var mre = new ManualResetEventSlim ();
1959 var ranOnDefault = false;
1960 var scheduler = new SynchronousScheduler ();
1962 Task parent = Task.Factory.StartNew (() => {
1963 Task.Factory.StartNew (() => {
1964 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1967 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
1969 Assert.IsTrue (mre.Wait (1000), "#1");
1970 Assert.IsTrue (ranOnDefault, "#2");
1974 public void LazyCancelationTest ()
1976 var source = new CancellationTokenSource ();
1978 var parent = new Task (delegate {});
1979 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
1981 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
1984 Assert.IsTrue (cont.Wait (1000), "#2");
1986 } catch (AggregateException ex) {
1987 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1992 public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
1995 var child = Task.Factory.StartNew (() => {
1996 inner = Task.Run (() => {
1997 throw new ApplicationException ();
1998 }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
2002 var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
2003 Assert.IsTrue (t.Wait (5000), "#1");
2004 Assert.AreEqual (1, counter, "#2");
2005 Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
2006 Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
2010 [Category("NotWorking")]
2011 public void TaskContinuationChainLeak()
2013 // Start cranking out tasks, starting each new task upon completion of and from inside the prior task.
2015 var tester = new TaskContinuationChainLeakTester ();
2017 tester.TasksPilledUp.WaitOne ();
2019 // Head task should be out of scope by now. Manually run the GC and expect that it gets collected.
2022 GC.WaitForPendingFinalizers ();
2025 // It's important that we do the asserting while the task recursion is still going, since that is the
2026 // crux of the problem scenario.
2034 class TaskContinuationChainLeakTester
2036 volatile bool m_bStop;
2038 ManualResetEvent mre = new ManualResetEvent (false);
2039 WeakReference<Task> headTaskWeakRef;
2041 public ManualResetEvent TasksPilledUp {
2049 headTaskWeakRef = new WeakReference<Task> (StartNewTask ());
2052 public Task StartNewTask ()
2057 if (++counter == 50)
2060 return Task.Factory.StartNew (DummyWorker).ContinueWith (task => StartNewTask ());
2068 public void Verify ()
2071 Assert.IsFalse (headTaskWeakRef.TryGetTarget (out task));