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);
812 var cntd = new CountdownEvent (2);
813 var cntd2 = new CountdownEvent (2);
815 bool r1 = false, r2 = false;
816 ThreadPool.QueueUserWorkItem (delegate {
818 r1 = t.Wait (1000) && t.Result;
822 Monitor.Pulse (monitor);
825 ThreadPool.QueueUserWorkItem (delegate {
827 r2 = t.Wait (1000) && t.Result;
831 Monitor.Pulse (monitor);
834 Assert.IsTrue (cntd.Wait (2000), "#1");
836 Assert.IsTrue (cntd2.Wait (2000), "#2");
837 Assert.IsTrue (r1, "r1");
838 Assert.IsTrue (r2, "r2");
840 // Wait for everything to finish to avoid overloading the tpool
846 Monitor.Wait (monitor);
853 public void DoubleTimeoutedWaitTest ()
855 var evt = new ManualResetEventSlim ();
856 var t = new Task (delegate { });
857 var cntd = new CountdownEvent (2);
859 bool r1 = false, r2 = false;
860 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
861 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
869 public void RunSynchronously ()
872 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
873 t.RunSynchronously ();
875 Assert.AreEqual (1, val, "#1");
877 t = new Task (() => { Thread.Sleep (0); val = 2; });
879 bool? previouslyQueued = null;
881 var scheduler = new MockScheduler ();
882 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
883 previouslyQueued = b;
886 t.RunSynchronously (scheduler);
888 Assert.AreEqual (2, val, "#2");
889 Assert.AreEqual (false, previouslyQueued, "#2a");
893 public void RunSynchronouslyArgumentChecks ()
895 Task t = new Task (() => { });
897 t.RunSynchronously (null);
899 } catch (ArgumentNullException) {
904 public void RunSynchronously_SchedulerException ()
906 var scheduler = new MockScheduler ();
907 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
908 throw new ApplicationException ();
911 Task t = new Task (() => { });
913 t.RunSynchronously (scheduler);
915 } catch (Exception e) {
916 Assert.AreEqual (t.Exception.InnerException, e);
921 public void RunSynchronouslyWithAttachedChildren ()
924 var t = new Task (() => {
925 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
927 t.RunSynchronously ();
928 Assert.IsTrue (result);
932 public void RunSynchronouslyOnContinuation ()
934 Task t = new Task<int> (() => 1);
935 t = t.ContinueWith (l => { });
937 t.RunSynchronously ();
939 } catch (InvalidOperationException) {
944 public void UnobservedExceptionOnFinalizerThreadTest ()
946 bool wasCalled = false;
947 TaskScheduler.UnobservedTaskException += (o, args) => {
951 var inner = new ApplicationException ();
952 Thread t = new Thread (delegate () {
953 Task.Factory.StartNew (() => { throw inner; });
960 GC.WaitForPendingFinalizers ();
962 Assert.IsTrue (wasCalled);
965 [Test, ExpectedException (typeof (InvalidOperationException))]
966 public void StartFinishedTaskTest ()
968 var t = Task.Factory.StartNew (delegate () { });
975 public void Start_NullArgument ()
977 var t = Task.Factory.StartNew (delegate () { });
981 } catch (ArgumentNullException) {
985 [Test, ExpectedException (typeof (InvalidOperationException))]
986 public void DisposeUnstartedTest ()
988 var t = new Task (() => { });
993 public void ThrowingUnrelatedCanceledExceptionTest ()
995 Task t = new Task (() => {
996 throw new TaskCanceledException ();
999 t.RunSynchronously ();
1000 Assert.IsTrue (t.IsFaulted);
1001 Assert.IsFalse (t.IsCanceled);
1005 public void CanceledContinuationExecuteSynchronouslyTest ()
1007 var source = new CancellationTokenSource();
1008 var token = source.Token;
1009 var evt = new ManualResetEventSlim ();
1010 bool result = false;
1011 bool thrown = false;
1013 var task = Task.Factory.StartNew (() => evt.Wait (100));
1014 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
1021 } catch (Exception ex) {
1025 Assert.IsTrue (task.IsCompleted);
1026 Assert.IsTrue (cont.IsCanceled);
1027 Assert.IsFalse (result);
1028 Assert.IsTrue (thrown);
1032 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
1034 Task innerTask = null;
1035 var testTask = new Task (() =>
1037 innerTask = new Task (() =>
1039 throw new InvalidOperationException ();
1040 }, TaskCreationOptions.AttachedToParent);
1041 innerTask.RunSynchronously ();
1043 testTask.RunSynchronously ();
1045 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
1046 Assert.IsNotNull (innerTask);
1047 Assert.IsTrue (innerTask.IsFaulted);
1048 Assert.IsNotNull (testTask.Exception);
1049 Assert.IsTrue (testTask.IsFaulted);
1050 Assert.IsNotNull (innerTask.Exception);
1054 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
1056 var continuationRan = false;
1057 var testTask = new Task (() =>
1059 var task = new Task (() =>
1061 throw new InvalidOperationException();
1062 }, TaskCreationOptions.AttachedToParent);
1063 task.RunSynchronously ();
1065 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1066 testTask.RunSynchronously ();
1067 onErrorTask.Wait (100);
1068 Assert.IsTrue (continuationRan);
1072 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
1074 var continuationRan = false;
1075 var testTask = new Task (() =>
1077 var task = new Task (() =>
1079 throw new InvalidOperationException();
1080 }, TaskCreationOptions.AttachedToParent);
1081 task.RunSynchronously();
1083 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
1084 testTask.RunSynchronously ();
1085 Assert.IsTrue (onErrorTask.IsCompleted);
1086 Assert.IsFalse (onErrorTask.IsFaulted);
1087 Assert.IsFalse (continuationRan);
1091 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
1093 var continuationRan = false;
1094 AggregateException e = null;
1095 var testTask = new Task (() =>
1097 var child1 = new Task (() =>
1099 var child2 = new Task (() =>
1101 throw new InvalidOperationException();
1102 }, TaskCreationOptions.AttachedToParent);
1103 child2.RunSynchronously ();
1104 }, TaskCreationOptions.AttachedToParent);
1106 child1.RunSynchronously();
1107 e = child1.Exception;
1108 child1.Exception.Handle (ex => true);
1110 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1111 testTask.RunSynchronously ();
1112 onErrorTask.Wait (100);
1113 Assert.IsNotNull (e);
1114 Assert.IsTrue (continuationRan);
1118 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1120 string result = "Failed";
1121 var testTask = new Task (() =>
1123 var child = new Task<string> (() =>
1126 }, TaskCreationOptions.AttachedToParent);
1127 child.RunSynchronously ();
1128 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1130 testTask.RunSynchronously ();
1132 Assert.AreEqual ("Success", result);
1136 public void InlineNotTrashingParentRelationship ()
1138 bool r1 = false, r2 = false;
1139 var t = new Task (() => {
1140 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1141 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1143 t.RunSynchronously ();
1150 public void AsyncWaitHandleSet ()
1152 var task = new TaskFactory ().StartNew (() => { });
1153 var ar = (IAsyncResult)task;
1154 Assert.IsFalse (ar.CompletedSynchronously, "#1");
1155 Assert.IsTrue (ar.AsyncWaitHandle.WaitOne (5000), "#2");
1159 public void StartOnBrokenScheduler ()
1161 var t = new Task (delegate { });
1164 t.Start (new ExceptionScheduler ());
1166 } catch (TaskSchedulerException e) {
1167 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1168 Assert.AreSame (e, t.Exception.InnerException, "#3");
1169 Assert.IsTrue (e.InnerException is ApplicationException, "#4");
1175 public void ContinuationOnBrokenScheduler ()
1177 var s = new ExceptionScheduler ();
1178 Task t = new Task(delegate {});
1180 var t2 = t.ContinueWith (delegate {
1181 }, TaskContinuationOptions.ExecuteSynchronously, s);
1183 var t3 = t.ContinueWith (delegate {
1184 }, TaskContinuationOptions.ExecuteSynchronously, s);
1189 Assert.IsTrue (t3.Wait (2000), "#0");
1191 } catch (AggregateException e) {
1194 Assert.AreEqual (TaskStatus.Faulted, t2.Status, "#2");
1195 Assert.AreEqual (TaskStatus.Faulted, t3.Status, "#3");
1199 public void Delay_Invalid ()
1203 } catch (ArgumentOutOfRangeException) {
1208 public void Delay_Start ()
1210 var t = Task.Delay (5000);
1213 } catch (InvalidOperationException) {
1218 public void Delay_Simple ()
1220 var t = Task.Delay (300);
1221 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1222 Assert.IsTrue (t.Wait (400), "#2");
1226 public void Delay_Cancelled ()
1228 var cancelation = new CancellationTokenSource ();
1230 var t = Task.Delay (5000, cancelation.Token);
1231 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1232 cancelation.Cancel ();
1236 } catch (AggregateException) {
1237 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1240 cancelation = new CancellationTokenSource ();
1241 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1242 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1243 cancelation.Cancel ();
1246 Assert.Fail ("#12");
1247 } catch (AggregateException) {
1248 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1253 public void Delay_TimeManagement ()
1255 var delay1 = Task.Delay(50);
1256 var delay2 = Task.Delay(25);
1257 Assert.IsTrue (Task.WhenAny(new[] { delay1, delay2 }).Wait (1000));
1258 Assert.AreEqual (TaskStatus.RanToCompletion, delay2.Status);
1262 public void WaitAny_WithNull ()
1264 var tasks = new [] {
1265 Task.FromResult (2),
1270 Task.WaitAny (tasks);
1272 } catch (ArgumentException) {
1277 public void WhenAll_Empty ()
1279 var tasks = new Task[0];
1281 Task t = Task.WhenAll(tasks);
1283 Assert.IsTrue(t.Wait(1000), "#1");
1287 public void WhenAll_WithNull ()
1290 Task.FromResult (2),
1295 Task.WhenAll (tasks);
1297 } catch (ArgumentException) {
1302 Task.WhenAll (tasks);
1304 } catch (ArgumentException) {
1309 public void WhenAll_Start ()
1311 Task[] tasks = new[] {
1312 Task.FromResult (2),
1315 var t = Task.WhenAll (tasks);
1316 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1321 } catch (InvalidOperationException) {
1325 new Task (delegate { }),
1328 t = Task.WhenAll (tasks);
1329 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1333 Assert.Fail ("#12");
1334 } catch (InvalidOperationException) {
1339 public void WhenAll_Cancelled ()
1341 var cancelation = new CancellationTokenSource ();
1342 var tasks = new Task[] {
1343 new Task (delegate { }),
1344 new Task (delegate { }, cancelation.Token)
1347 cancelation.Cancel ();
1349 var t = Task.WhenAll (tasks);
1350 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1354 Assert.IsTrue (t.Wait (1000), "#2");
1355 Assert.Fail ("#2a");
1356 } catch (AggregateException e) {
1357 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1362 public void WhenAll_Faulted ()
1364 var tcs = new TaskCompletionSource<object> ();
1365 tcs.SetException (new ApplicationException ());
1367 var tcs2 = new TaskCompletionSource<object> ();
1368 tcs2.SetException (new InvalidTimeZoneException ());
1370 var cancelation = new CancellationTokenSource ();
1371 var tasks = new Task[] {
1372 new Task (delegate { }),
1373 new Task (delegate { }, cancelation.Token),
1378 cancelation.Cancel ();
1380 var t = Task.WhenAll (tasks);
1381 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1385 Assert.IsTrue (t.Wait (1000), "#2");
1386 Assert.Fail ("#2a");
1387 } catch (AggregateException e) {
1388 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1389 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1394 public void WhenAll ()
1396 var t1 = new Task (delegate { });
1397 var t2 = new Task (delegate { t1.Start (); });
1399 var tasks = new Task[] {
1404 var t = Task.WhenAll (tasks);
1405 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1408 Assert.IsTrue (t.Wait (1000), "#2");
1412 public void WhenAllResult_Empty ()
1414 var tasks = new Task<int>[0];
1416 Task<int[]> t = Task.WhenAll(tasks);
1418 Assert.IsTrue(t.Wait(1000), "#1");
1419 Assert.IsNotNull(t.Result, "#2");
1420 Assert.AreEqual(t.Result.Length, 0, "#3");
1424 public void WhenAllResult_WithNull ()
1427 Task.FromResult (2),
1432 Task.WhenAll<int> (tasks);
1434 } catch (ArgumentException) {
1439 Task.WhenAll<int> (tasks);
1441 } catch (ArgumentException) {
1446 public void WhenAllResult_Cancelled ()
1448 var cancelation = new CancellationTokenSource ();
1449 var tasks = new [] {
1450 new Task<int> (delegate { return 9; }),
1451 new Task<int> (delegate { return 1; }, cancelation.Token)
1454 cancelation.Cancel ();
1456 var t = Task.WhenAll (tasks);
1457 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1461 Assert.IsTrue (t.Wait (1000), "#2");
1462 Assert.Fail ("#2a");
1463 } catch (AggregateException e) {
1464 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1470 } catch (AggregateException) {
1475 public void WhenAllResult ()
1477 var t1 = new Task<string> (delegate { return "a"; });
1478 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1480 var tasks = new [] {
1485 var t = Task.WhenAll<string> (tasks);
1486 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1489 Assert.IsTrue (t.Wait (1000), "#2");
1490 Assert.AreEqual (2, t.Result.Length, "#3");
1491 Assert.AreEqual ("a", t.Result[0], "#3a");
1492 Assert.AreEqual ("b", t.Result[1], "#3b");
1496 public void WhenAllResult_Completed ()
1499 Task.FromResult (1),
1503 var t = Task.WhenAll<int> (tasks);
1504 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1505 Assert.AreEqual (2, t.Result.Length, "#2");
1506 Assert.AreEqual (1, t.Result[0], "#2a");
1507 Assert.AreEqual (2, t.Result[1], "#2b");
1511 public void WhenAny_WithNull ()
1513 var tasks = new Task[] {
1514 Task.FromResult (2),
1519 Task.WhenAny (tasks);
1521 } catch (ArgumentException) {
1526 Task.WhenAny (tasks);
1528 } catch (ArgumentException) {
1532 Task.WhenAny (new Task[0]);
1534 } catch (ArgumentException) {
1539 public void WhenAny_Start ()
1541 Task[] tasks = new[] {
1542 Task.FromResult (2),
1545 var t = Task.WhenAny (tasks);
1546 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1551 } catch (InvalidOperationException) {
1555 new Task (delegate { }),
1558 t = Task.WhenAny (tasks);
1559 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1563 Assert.Fail ("#12");
1564 } catch (InvalidOperationException) {
1569 public void WhenAny_Cancelled ()
1571 var cancelation = new CancellationTokenSource ();
1572 var tasks = new Task[] {
1573 new Task (delegate { }),
1574 new Task (delegate { }, cancelation.Token)
1577 cancelation.Cancel ();
1579 var t = Task.WhenAny (tasks);
1580 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1583 Assert.IsTrue (t.Wait (1000), "#2");
1584 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1588 public void WhenAny_Faulted ()
1590 var tcs = new TaskCompletionSource<object> ();
1591 tcs.SetException (new ApplicationException ());
1593 var tcs2 = new TaskCompletionSource<object> ();
1594 tcs2.SetException (new InvalidTimeZoneException ());
1596 var cancelation = new CancellationTokenSource ();
1597 var tasks = new Task[] {
1598 new Task (delegate { }),
1600 new Task (delegate { }, cancelation.Token),
1604 cancelation.Cancel ();
1606 var t = Task.WhenAny (tasks);
1607 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1610 Assert.IsTrue (t.Wait (1000), "#2");
1611 Assert.IsNull (t.Exception, "#3");
1613 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1617 public void WhenAny ()
1619 var t1 = new Task (delegate { });
1620 var t2 = new Task (delegate { t1.Start (); });
1622 var tasks = new Task[] {
1627 var t = Task.WhenAny (tasks);
1628 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1631 Assert.IsTrue (t.Wait (1000), "#2");
1632 Assert.IsNotNull (t.Result, "#3");
1636 public void WhenAnyResult_WithNull ()
1638 var tasks = new [] {
1639 Task.FromResult (2),
1644 Task.WhenAny<int> (tasks);
1646 } catch (ArgumentException) {
1651 Task.WhenAny<int> (tasks);
1653 } catch (ArgumentException) {
1657 Task.WhenAny<short> (new Task<short>[0]);
1659 } catch (ArgumentException) {
1664 public void WhenAnyResult_Start ()
1667 Task.FromResult (2),
1670 var t = Task.WhenAny<int> (tasks);
1671 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1676 } catch (InvalidOperationException) {
1680 new Task<int> (delegate { return 55; }),
1683 t = Task.WhenAny<int> (tasks);
1684 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1688 Assert.Fail ("#12");
1689 } catch (InvalidOperationException) {
1694 public void WhenAnyResult_Cancelled ()
1696 var cancelation = new CancellationTokenSource ();
1697 var tasks = new [] {
1698 new Task<double> (delegate { return 1.1; }),
1699 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1702 cancelation.Cancel ();
1704 var t = Task.WhenAny<double> (tasks);
1705 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1708 Assert.IsTrue (t.Wait (1000), "#2");
1709 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1713 public void WhenAnyResult_Faulted ()
1715 var tcs = new TaskCompletionSource<object> ();
1716 tcs.SetException (new ApplicationException ());
1718 var tcs2 = new TaskCompletionSource<object> ();
1719 tcs2.SetException (new InvalidTimeZoneException ());
1721 var cancelation = new CancellationTokenSource ();
1722 var tasks = new Task<object>[] {
1723 new Task<object> (delegate { return null; }),
1725 new Task<object> (delegate { return ""; }, cancelation.Token),
1729 cancelation.Cancel ();
1731 var t = Task.WhenAny<object> (tasks);
1732 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1735 Assert.IsTrue (t.Wait (1000), "#2");
1736 Assert.IsNull (t.Exception, "#3");
1738 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1742 public void WhenAnyResult ()
1744 var t1 = new Task<byte> (delegate { return 3; });
1745 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1747 var tasks = new [] {
1752 var t = Task.WhenAny<byte> (tasks);
1753 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1756 Assert.IsTrue (t.Wait (1000), "#2");
1757 Assert.IsTrue (t.Result.Result > 1, "#3");
1761 public void ContinueWith_StateValue ()
1763 var t = Task.Factory.StartNew (l => {
1764 Assert.AreEqual (1, l, "a-1");
1767 var c = t.ContinueWith ((a, b) => {
1768 Assert.AreEqual (t, a, "c-1");
1769 Assert.AreEqual (2, b, "c-2");
1772 var d = t.ContinueWith ((a, b) => {
1773 Assert.AreEqual (t, a, "d-1");
1774 Assert.AreEqual (3, b, "d-2");
1778 Assert.IsTrue (d.Wait (1000), "#1");
1780 Assert.AreEqual (1, t.AsyncState, "#2");
1781 Assert.AreEqual (2, c.AsyncState, "#3");
1782 Assert.AreEqual (3, d.AsyncState, "#4");
1786 public void ContinueWith_StateValueGeneric ()
1788 var t = Task<int>.Factory.StartNew (l => {
1789 Assert.AreEqual (1, l, "a-1");
1793 var c = t.ContinueWith ((a, b) => {
1794 Assert.AreEqual (t, a, "c-1");
1795 Assert.AreEqual (2, b, "c-2");
1799 var d = t.ContinueWith ((a, b) => {
1800 Assert.AreEqual (t, a, "d-1");
1801 Assert.AreEqual (3, b, "d-2");
1805 Assert.IsTrue (d.Wait (1000), "#1");
1807 Assert.AreEqual (1, t.AsyncState, "#2");
1808 Assert.AreEqual (80, t.Result, "#2r");
1809 Assert.AreEqual (2, c.AsyncState, "#3");
1810 Assert.AreEqual ("c", c.Result, "#3r");
1811 Assert.AreEqual (3, d.AsyncState, "#4");
1812 Assert.AreEqual ('d', d.Result, "#3r");
1816 public void ContinueWith_CustomScheduleRejected ()
1818 var scheduler = new NonInlineableScheduler ();
1819 var t = Task.Factory.StartNew (delegate { }).
1820 ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
1822 Assert.IsTrue (t.Wait (5000));
1826 public void FromResult ()
1828 var t = Task.FromResult<object> (null);
1829 Assert.IsTrue (t.IsCompleted, "#1");
1830 Assert.AreEqual (null, t.Result, "#2");
1836 public void LongRunning ()
1840 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1842 Assert.IsTrue (t.Wait (100));
1843 Assert.IsTrue ((bool)is_tp, "#1");
1844 Assert.IsTrue ((bool)is_bg, "#2");
1848 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1851 Assert.IsTrue (t.Wait (100));
1852 Assert.IsFalse ((bool) is_tp, "#11");
1853 Assert.IsTrue ((bool) is_bg, "#12");
1857 public void Run_ArgumentCheck ()
1860 Task.Run (null as Action);
1862 } catch (ArgumentNullException) {
1869 bool ranOnDefaultScheduler = false;
1870 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1871 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1873 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1877 public void Run_Cancel ()
1879 var t = Task.Run (() => 1, new CancellationToken (true));
1883 } catch (AggregateException) {
1886 Assert.IsTrue (t.IsCanceled, "#2");
1890 public void Run_ExistingTaskT ()
1892 var t = new Task<int> (() => 5);
1893 var t2 = Task.Run (() => { t.Start (); return t; });
1895 Assert.IsTrue (t2.Wait (1000), "#1");
1896 Assert.AreEqual (5, t2.Result, "#2");
1900 public void Run_ExistingTask ()
1902 var t = new Task (delegate { throw new Exception ("Foo"); });
1903 var t2 = Task.Run (() => { t.Start (); return t; });
1908 } catch (Exception) {}
1910 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1914 public void DenyChildAttachTest ()
1916 var mre = new ManualResetEventSlim ();
1918 Task parent = Task.Factory.StartNew (() => {
1919 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1920 }, TaskCreationOptions.DenyChildAttach);
1921 Assert.IsTrue (parent.Wait (1000), "#1");
1923 Assert.IsTrue (nested.Wait (2000), "#2");
1926 class SynchronousScheduler : TaskScheduler
1928 protected override IEnumerable<Task> GetScheduledTasks ()
1930 throw new NotImplementedException ();
1933 protected override void QueueTask (Task task)
1935 TryExecuteTaskInline (task, false);
1938 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1940 return base.TryExecuteTask (task);
1945 public void HideSchedulerTest ()
1947 var mre = new ManualResetEventSlim ();
1948 var ranOnDefault = false;
1949 var scheduler = new SynchronousScheduler ();
1951 Task parent = Task.Factory.StartNew (() => {
1952 Task.Factory.StartNew (() => {
1953 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1956 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
1958 Assert.IsTrue (mre.Wait (1000), "#1");
1959 Assert.IsTrue (ranOnDefault, "#2");
1963 public void LazyCancelationTest ()
1965 var source = new CancellationTokenSource ();
1967 var parent = new Task (delegate {});
1968 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
1970 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
1973 Assert.IsTrue (cont.Wait (1000), "#2");
1975 } catch (AggregateException ex) {
1976 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1981 public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
1984 var child = Task.Factory.StartNew (() => {
1985 inner = Task.Run (() => {
1986 throw new ApplicationException ();
1987 }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
1991 var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
1992 Assert.IsTrue (t.Wait (5000), "#1");
1993 Assert.AreEqual (1, counter, "#2");
1994 Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
1995 Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
1999 [Category("NotWorking")]
2000 public void TaskContinuationChainLeak()
2002 // Start cranking out tasks, starting each new task upon completion of and from inside the prior task.
2004 var tester = new TaskContinuationChainLeakTester ();
2006 tester.TasksPilledUp.WaitOne ();
2008 // Head task should be out of scope by now. Manually run the GC and expect that it gets collected.
2011 GC.WaitForPendingFinalizers ();
2014 // It's important that we do the asserting while the task recursion is still going, since that is the
2015 // crux of the problem scenario.
2023 class TaskContinuationChainLeakTester
2025 volatile bool m_bStop;
2027 ManualResetEvent mre = new ManualResetEvent (false);
2028 WeakReference<Task> headTaskWeakRef;
2030 public ManualResetEvent TasksPilledUp {
2038 headTaskWeakRef = new WeakReference<Task> (StartNewTask ());
2041 public Task StartNewTask ()
2046 if (++counter == 50)
2049 return Task.Factory.StartNew (DummyWorker).ContinueWith (task => StartNewTask ());
2057 public void Verify ()
2060 Assert.IsFalse (headTaskWeakRef.TryGetTarget (out task));