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
32 using System.Threading;
33 using System.Threading.Tasks;
34 using System.Collections.Generic;
35 using NUnit.Framework;
38 using NUnit.Framework.SyntaxHelpers;
41 namespace MonoTests.System.Threading.Tasks
44 public class TaskTests
46 class MockScheduler : TaskScheduler
48 public event Action<Task, bool> TryExecuteTaskInlineHandler;
50 protected override IEnumerable<Task> GetScheduledTasks ()
52 throw new NotImplementedException ();
55 protected override void QueueTask (Task task)
60 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
62 if (TryExecuteTaskInlineHandler != null)
63 TryExecuteTaskInlineHandler (task, taskWasPreviouslyQueued);
65 return base.TryExecuteTask (task);
69 class NonInlineableScheduler : TaskScheduler
71 protected override IEnumerable<Task> GetScheduledTasks ()
73 throw new NotImplementedException ();
76 protected override void QueueTask (Task task)
78 if (!base.TryExecuteTask (task))
79 throw new ApplicationException ();
82 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
88 class ExceptionScheduler : TaskScheduler
90 protected override IEnumerable<Task> GetScheduledTasks ()
92 throw new ApplicationException ("1");
95 protected override void QueueTask (Task task)
97 throw new ApplicationException ("2");
100 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
102 throw new ApplicationException ("3");
107 int completionPortThreads;
111 object cleanup_mutex = new object ();
112 List<Task> cleanup_list;
117 ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
118 ThreadPool.SetMinThreads (1, 1);
120 tasks = new Task[max];
121 cleanup_list = new List<Task> ();
125 public void Teardown()
127 ThreadPool.SetMinThreads (workerThreads, completionPortThreads);
129 lock (cleanup_mutex) {
130 l = cleanup_list.ToArray ();
134 } catch (Exception) {
138 void AddToCleanup (Task[] tasks) {
139 lock (cleanup_mutex) {
140 foreach (var t in tasks)
141 cleanup_list.Add (t);
145 void AddToCleanup (Task task) {
146 lock (cleanup_mutex) {
147 cleanup_list.Add (task);
151 void InitWithDelegate(Action action)
153 for (int i = 0; i < max; i++) {
154 tasks[i] = Task.Factory.StartNew(action);
156 AddToCleanup (tasks);
160 public void WaitAnyTest()
162 ParallelTestHelper.Repeat (delegate {
166 InitWithDelegate(delegate {
167 int times = Interlocked.Exchange (ref flag, 1);
169 SpinWait sw = new SpinWait ();
170 while (finished == 0) sw.SpinOnce ();
172 Interlocked.Increment (ref finished);
176 int index = Task.WaitAny(tasks, 1000);
178 Assert.AreNotEqual (-1, index, "#3");
179 Assert.AreEqual (1, flag, "#1");
180 Assert.AreEqual (1, finished, "#2");
185 public void WaitAny_Empty ()
187 Assert.AreEqual (-1, Task.WaitAny (new Task[0]));
191 public void WaitAny_Zero ()
193 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { })}, 0), "#1");
194 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { }) }, 20), "#1");
198 public void WaitAny_Cancelled ()
200 var cancelation = new CancellationTokenSource ();
201 var tasks = new Task[] {
202 new Task (delegate { }),
203 new Task (delegate { }, cancelation.Token)
206 cancelation.Cancel ();
208 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
209 Assert.IsTrue (tasks[1].IsCompleted, "#2");
210 Assert.IsTrue (tasks[1].IsCanceled, "#3");
214 public void WaitAny_CancelledWithoutExecution ()
216 var cancelation = new CancellationTokenSource ();
217 var tasks = new Task[] {
218 new Task (delegate { }),
219 new Task (delegate { })
223 var mre = new ManualResetEventSlim (false);
224 ThreadPool.QueueUserWorkItem (delegate {
225 res = Task.WaitAny (tasks, 20);
229 cancelation.Cancel ();
230 Assert.IsTrue (mre.Wait (1000), "#1");
231 Assert.AreEqual (-1, res);
235 public void WaitAny_OneException ()
237 var mre = new ManualResetEventSlim (false);
238 var tasks = new Task[] {
239 Task.Factory.StartNew (delegate { mre.Wait (5000); }),
240 Task.Factory.StartNew (delegate { throw new ApplicationException (); })
243 Assert.AreEqual (1, Task.WaitAny (tasks, 3000), "#1");
244 Assert.IsFalse (tasks[0].IsCompleted, "#2");
245 Assert.IsTrue (tasks[1].IsFaulted, "#3");
251 public void WaitAny_SingleCanceled ()
253 var src = new CancellationTokenSource ();
254 var t = Task.Factory.StartNew (() => { Thread.Sleep (200); src.Cancel (); src.Token.ThrowIfCancellationRequested (); }, src.Token);
255 Assert.AreEqual (0, Task.WaitAny (new [] { t }));
258 public void WaitAny_ManyExceptions ()
260 CountdownEvent cde = new CountdownEvent (3);
262 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
263 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
264 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
267 Assert.IsTrue (cde.Wait (1000), "#1");
270 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#2");
271 } catch (AggregateException e) {
272 Assert.AreEqual (3, e.InnerExceptions.Count, "#3");
277 public void WaitAny_ManyCanceled ()
279 var cancellation = new CancellationToken (true);
281 Task.Factory.StartNew (delegate { }, cancellation),
282 Task.Factory.StartNew (delegate { }, cancellation),
283 Task.Factory.StartNew (delegate { }, cancellation)
287 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#1");
288 } catch (AggregateException e) {
289 Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
294 public void WaitAllTest ()
296 ParallelTestHelper.Repeat (delegate {
298 InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
300 Assert.AreEqual(max, achieved, "#1");
305 public void WaitAll_ManyTasks ()
307 for (int r = 0; r < 2000; ++r) {
308 var tasks = new Task[60];
310 for (int i = 0; i < tasks.Length; i++) {
311 tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
313 AddToCleanup (tasks);
315 Assert.IsTrue (Task.WaitAll (tasks, 5000));
320 public void WaitAll_Zero ()
322 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 0), "#0");
323 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 10), "#1");
327 public void WaitAll_WithExceptions ()
329 InitWithDelegate (delegate { throw new ApplicationException (); });
332 Task.WaitAll (tasks);
334 } catch (AggregateException e) {
335 Assert.AreEqual (6, e.InnerExceptions.Count, "#2");
338 Assert.IsNotNull (tasks[0].Exception, "#3");
342 public void WaitAll_TimeoutWithExceptionsAfter ()
344 CountdownEvent cde = new CountdownEvent (2);
345 var mre = new ManualResetEvent (false);
347 Task.Factory.StartNew (delegate { Assert.IsTrue (mre.WaitOne (10000), "#0"); }),
348 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
349 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
352 Assert.IsTrue (cde.Wait (5000), "#1");
353 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
358 Task.WaitAll (tasks, 1000);
360 } catch (AggregateException e) {
361 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
366 public void WaitAll_TimeoutWithExceptionsBefore ()
368 CountdownEvent cde = new CountdownEvent (2);
369 var mre = new ManualResetEvent (false);
371 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
372 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
373 Task.Factory.StartNew (delegate { mre.WaitOne (); })
376 Assert.IsTrue (cde.Wait (1000), "#1");
377 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
382 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
384 } catch (AggregateException e) {
385 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
390 public void WaitAll_Cancelled ()
392 var cancelation = new CancellationTokenSource ();
393 var tasks = new Task[] {
394 new Task (delegate { cancelation.Cancel (); }),
395 new Task (delegate { }, cancelation.Token)
401 Task.WaitAll (tasks);
403 } catch (AggregateException e) {
404 var inner = (TaskCanceledException) e.InnerException;
405 Assert.AreEqual (tasks[1], inner.Task, "#2");
408 Assert.IsTrue (tasks[0].IsCompleted, "#3");
409 Assert.IsTrue (tasks[1].IsCanceled, "#4");
413 public void WaitAll_CancelledAndTimeout ()
415 var ct = new CancellationToken (true);
416 var t1 = new Task (() => {}, ct);
417 var t2 = Task.Delay (3000);
418 Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
422 public void WaitAllExceptionThenCancelled ()
424 var cancelation = new CancellationTokenSource ();
425 var tasks = new Task[] {
426 new Task (delegate { cancelation.Cancel (); throw new ApplicationException (); }),
427 new Task (delegate { }, cancelation.Token)
433 Task.WaitAll (tasks);
435 } catch (AggregateException e) {
436 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#2");
437 var inner = (TaskCanceledException) e.InnerExceptions[1];
438 Assert.AreEqual (tasks[1], inner.Task, "#3");
441 Assert.IsTrue (tasks[0].IsCompleted, "#4");
442 Assert.IsTrue (tasks[1].IsCanceled, "#5");
446 public void WaitAll_StartedUnderWait ()
448 var task1 = new Task (delegate { });
450 ThreadPool.QueueUserWorkItem (delegate {
451 // Sleep little to let task to start and hit internal wait
456 Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
460 public void CancelBeforeStart ()
462 var src = new CancellationTokenSource ();
464 Task t = new Task (delegate { }, src.Token);
466 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
471 } catch (InvalidOperationException) {
476 public void Wait_CancelledTask ()
478 var src = new CancellationTokenSource ();
480 Task t = new Task (delegate { }, src.Token);
486 } catch (AggregateException e) {
487 var details = (TaskCanceledException) e.InnerException;
488 Assert.AreEqual (t, details.Task, "#1e");
494 } catch (AggregateException e) {
495 var details = (TaskCanceledException) e.InnerException;
496 Assert.AreEqual (t, details.Task, "#2e");
497 Assert.IsNull (details.Task.Exception, "#2e2");
502 public void Wait_Inlined ()
504 bool? previouslyQueued = null;
506 var scheduler = new MockScheduler ();
507 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
508 previouslyQueued = b;
511 var tf = new TaskFactory (scheduler);
512 var t = tf.StartNew (() => { });
515 Assert.AreEqual (true, previouslyQueued);
519 public void CreationWhileInitiallyCanceled ()
521 var token = new CancellationToken (true);
522 var task = new Task (() => { }, token);
527 } catch (InvalidOperationException) {
533 } catch (AggregateException e) {
534 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
537 Assert.IsTrue (task.IsCanceled, "#4");
541 public void ContinueWithInvalidArguments ()
543 var task = new Task (() => { });
545 task.ContinueWith (null);
547 } catch (ArgumentNullException e) {
551 task.ContinueWith (delegate { }, null);
553 } catch (ArgumentNullException e) {
557 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
559 } catch (ArgumentOutOfRangeException) {
563 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
565 } catch (ArgumentOutOfRangeException) {
570 public void ContinueWithOnAnyTestCase()
572 ParallelTestHelper.Repeat (delegate {
575 Task t = Task.Factory.StartNew(delegate { });
576 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
577 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
578 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
579 Assert.IsNull(cont.Exception, "#1");
580 Assert.IsNotNull(cont, "#2");
581 Assert.IsTrue(result, "#3");
586 public void ContinueWithOnCompletedSuccessfullyTestCase()
588 ParallelTestHelper.Repeat (delegate {
591 Task t = Task.Factory.StartNew(delegate { });
592 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
593 Assert.IsTrue (t.Wait(1000), "#4");
594 Assert.IsTrue (cont.Wait(1000), "#5");
596 Assert.IsNull(cont.Exception, "#1");
597 Assert.IsNotNull(cont, "#2");
598 Assert.IsTrue(result, "#3");
603 public void ContinueWithOnAbortedTestCase()
606 bool taskResult = false;
608 CancellationTokenSource src = new CancellationTokenSource ();
609 Task t = new Task (delegate { taskResult = true; }, src.Token);
611 Task cont = t.ContinueWith (delegate { result = true; },
612 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
616 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
617 Assert.IsTrue (cont.IsCompleted, "#1b");
618 Assert.IsTrue (result, "#1c");
623 } catch (InvalidOperationException) {
626 Assert.IsTrue (cont.Wait (1000), "#3");
628 Assert.IsFalse (taskResult, "#4");
630 Assert.IsNull (cont.Exception, "#5");
631 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
635 public void ContinueWithOnFailedTestCase()
637 ParallelTestHelper.Repeat (delegate {
640 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
641 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
643 Assert.IsTrue (cont.Wait(1000), "#0");
644 Assert.IsNotNull (t.Exception, "#1");
645 Assert.IsNotNull (cont, "#2");
646 Assert.IsTrue (result, "#3");
651 public void ContinueWithWithStart ()
653 Task t = new Task<int> (() => 1);
654 t = t.ContinueWith (l => { });
658 } catch (InvalidOperationException) {
663 public void ContinueWithChildren ()
665 ParallelTestHelper.Repeat (delegate {
668 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
670 var mre = new ManualResetEvent (false);
671 t.ContinueWith (l => {
676 Assert.IsTrue (mre.WaitOne (1000), "#1");
677 Assert.IsTrue (result, "#2");
682 public void ContinueWithDifferentOptionsAreCanceledTest ()
684 var mre = new ManualResetEventSlim ();
685 var task = Task.Factory.StartNew (() => mre.Wait (200));
686 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
687 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
688 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
691 contSuccess.Wait (100);
693 Assert.IsTrue (contSuccess.IsCompleted);
694 Assert.IsTrue (contFailed.IsCompleted);
695 Assert.IsTrue (contCanceled.IsCompleted);
696 Assert.IsFalse (contSuccess.IsCanceled);
697 Assert.IsTrue (contFailed.IsCanceled);
698 Assert.IsTrue (contCanceled.IsCanceled);
702 public void MultipleTasks()
704 ParallelTestHelper.Repeat (delegate {
705 bool r1 = false, r2 = false, r3 = false;
707 Task t1 = Task.Factory.StartNew(delegate {
710 Task t2 = Task.Factory.StartNew(delegate {
713 Task t3 = Task.Factory.StartNew(delegate {
721 Assert.IsTrue(r1, "#1");
722 Assert.IsTrue(r2, "#2");
723 Assert.IsTrue(r3, "#3");
728 public void WaitChildTestCase()
730 ParallelTestHelper.Repeat (delegate {
731 bool r1 = false, r2 = false, r3 = false;
732 var mre = new ManualResetEventSlim (false);
733 var mreStart = new ManualResetEventSlim (false);
735 Task t = Task.Factory.StartNew(delegate {
736 Task.Factory.StartNew(delegate {
739 }, TaskCreationOptions.AttachedToParent);
740 Task.Factory.StartNew(delegate {
742 }, TaskCreationOptions.AttachedToParent);
743 Task.Factory.StartNew(delegate {
745 }, TaskCreationOptions.AttachedToParent);
750 Assert.IsFalse (t.Wait (10), "#0a");
752 Assert.IsTrue (t.Wait (500), "#0b");
753 Assert.IsTrue(r2, "#1");
754 Assert.IsTrue(r3, "#2");
755 Assert.IsTrue(r1, "#3");
756 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
763 public void WaitingForChildrenToComplete ()
766 var mre = new ManualResetEvent (false);
768 parent_wfc = Task.Factory.StartNew (() => {
769 nested = Task.Factory.StartNew (() => {
770 Assert.IsTrue (mre.WaitOne (4000), "parent_wfc needs to be set first");
771 Assert.IsFalse (parent_wfc.Wait (10), "#1a");
772 Assert.AreEqual (TaskStatus.WaitingForChildrenToComplete, parent_wfc.Status, "#1b");
773 }, TaskCreationOptions.AttachedToParent).ContinueWith (l => {
774 Assert.IsTrue (parent_wfc.Wait (2000), "#2a");
775 Assert.AreEqual (TaskStatus.RanToCompletion, parent_wfc.Status, "#2b");
776 }, TaskContinuationOptions.ExecuteSynchronously);
780 Assert.IsTrue (parent_wfc.Wait (2000), "#3");
781 Assert.IsTrue (nested.Wait (2000), "#4");
785 public void WaitChildWithContinuationAttachedTest ()
788 var task = new Task(() =>
790 Task.Factory.StartNew(() => {
792 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
795 }, TaskContinuationOptions.AttachedToParent);
799 Assert.IsTrue (result);
803 public void WaitChildWithContinuationNotAttachedTest ()
805 var task = new Task(() =>
807 Task.Factory.StartNew(() => {
809 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
814 Assert.IsTrue (task.Wait(400));
818 public void WaitChildWithNesting ()
821 var t = Task.Factory.StartNew (() => {
822 Task.Factory.StartNew (() => {
823 Task.Factory.StartNew (() => {
826 }, TaskCreationOptions.AttachedToParent);
827 }, TaskCreationOptions.AttachedToParent);
829 Assert.IsTrue (t.Wait (4000), "#1");
830 Assert.IsTrue (result, "#2");
834 public void DoubleWaitTest ()
836 ParallelTestHelper.Repeat (delegate {
837 var evt = new ManualResetEventSlim ();
838 var monitor = new object ();
840 var t = Task.Factory.StartNew (delegate {
841 var r = evt.Wait (5000);
844 Monitor.Pulse (monitor);
846 return r ? 1 : 10; //1 -> ok, 10 -> evt wait failed
848 var cntd = new CountdownEvent (2);
849 var cntd2 = new CountdownEvent (2);
852 ThreadPool.QueueUserWorkItem (delegate {
855 r1 = 20; // 20 -> task wait failed
856 else if (t.Result != 1)
857 r1 = 30 + t.Result; // 30 -> task result is bad
863 Monitor.Pulse (monitor);
866 ThreadPool.QueueUserWorkItem (delegate {
869 r2 = 40; // 40 -> task wait failed
870 else if (t.Result != 1)
871 r2 = 50 + t.Result; // 50 -> task result is bad
878 Monitor.Pulse (monitor);
881 Assert.IsTrue (cntd.Wait (2000), "#1");
883 Assert.IsTrue (cntd2.Wait (2000), "#2");
884 Assert.AreEqual (2, r1, "r1");
885 Assert.AreEqual (3, r2, "r2");
887 // Wait for everything to finish to avoid overloading the tpool
893 Monitor.Wait (monitor);
900 public void DoubleTimeoutedWaitTest ()
902 var evt = new ManualResetEventSlim ();
903 var t = new Task (delegate { });
904 var cntd = new CountdownEvent (2);
906 bool r1 = false, r2 = false;
907 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
908 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
916 public void RunSynchronously ()
919 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
920 t.RunSynchronously ();
922 Assert.AreEqual (1, val, "#1");
924 t = new Task (() => { Thread.Sleep (0); val = 2; });
926 bool? previouslyQueued = null;
928 var scheduler = new MockScheduler ();
929 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
930 previouslyQueued = b;
933 t.RunSynchronously (scheduler);
935 Assert.AreEqual (2, val, "#2");
936 Assert.AreEqual (false, previouslyQueued, "#2a");
940 public void RunSynchronouslyArgumentChecks ()
942 Task t = new Task (() => { });
944 t.RunSynchronously (null);
946 } catch (ArgumentNullException) {
951 public void RunSynchronously_SchedulerException ()
953 var scheduler = new MockScheduler ();
954 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
955 throw new ApplicationException ();
958 Task t = new Task (() => { });
960 t.RunSynchronously (scheduler);
962 } catch (Exception e) {
963 Assert.AreEqual (t.Exception.InnerException, e);
968 public void RunSynchronouslyWithAttachedChildren ()
971 var t = new Task (() => {
972 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
974 t.RunSynchronously ();
975 Assert.IsTrue (result);
979 public void RunSynchronouslyOnContinuation ()
981 Task t = new Task<int> (() => 1);
982 t = t.ContinueWith (l => { });
984 t.RunSynchronously ();
986 } catch (InvalidOperationException) {
991 public void UnobservedExceptionOnFinalizerThreadTest ()
993 bool wasCalled = false;
994 TaskScheduler.UnobservedTaskException += (o, args) => {
998 var inner = new ApplicationException ();
999 Thread t = new Thread (delegate () {
1000 Task.Factory.StartNew (() => { throw inner; });
1004 Thread.Sleep (1000);
1006 Thread.Sleep (1000);
1007 GC.WaitForPendingFinalizers ();
1009 Assert.IsTrue (wasCalled);
1012 [Test, ExpectedException (typeof (InvalidOperationException))]
1013 public void StartFinishedTaskTest ()
1015 var t = Task.Factory.StartNew (delegate () { });
1022 public void Start_NullArgument ()
1024 var t = new Task (() => { });
1028 } catch (ArgumentNullException) {
1032 [Test, ExpectedException (typeof (InvalidOperationException))]
1033 public void DisposeUnstartedTest ()
1035 var t = new Task (() => { });
1040 public void ThrowingUnrelatedCanceledExceptionTest ()
1042 Task t = new Task (() => {
1043 throw new TaskCanceledException ();
1046 t.RunSynchronously ();
1047 Assert.IsTrue (t.IsFaulted);
1048 Assert.IsFalse (t.IsCanceled);
1052 public void CanceledContinuationExecuteSynchronouslyTest ()
1054 var source = new CancellationTokenSource();
1055 var token = source.Token;
1056 var evt = new ManualResetEventSlim ();
1057 bool result = false;
1058 bool thrown = false;
1060 var task = Task.Factory.StartNew (() => evt.Wait (100));
1061 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
1068 } catch (Exception ex) {
1072 Assert.IsTrue (task.IsCompleted);
1073 Assert.IsTrue (cont.IsCanceled);
1074 Assert.IsFalse (result);
1075 Assert.IsTrue (thrown);
1079 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
1081 Task innerTask = null;
1082 var testTask = new Task (() =>
1084 innerTask = new Task (() =>
1086 throw new InvalidOperationException ();
1087 }, TaskCreationOptions.AttachedToParent);
1088 innerTask.RunSynchronously ();
1090 testTask.RunSynchronously ();
1092 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
1093 Assert.IsNotNull (innerTask);
1094 Assert.IsTrue (innerTask.IsFaulted);
1095 Assert.IsNotNull (testTask.Exception);
1096 Assert.IsTrue (testTask.IsFaulted);
1097 Assert.IsNotNull (innerTask.Exception);
1101 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
1103 var continuationRan = false;
1104 var testTask = new Task (() =>
1106 var task = new Task (() =>
1108 throw new InvalidOperationException();
1109 }, TaskCreationOptions.AttachedToParent);
1110 task.RunSynchronously ();
1112 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1113 testTask.RunSynchronously ();
1114 onErrorTask.Wait (100);
1115 Assert.IsTrue (continuationRan);
1119 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
1121 var continuationRan = false;
1122 var testTask = new Task (() =>
1124 var task = new Task (() =>
1126 throw new InvalidOperationException();
1127 }, TaskCreationOptions.AttachedToParent);
1128 task.RunSynchronously();
1130 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
1131 testTask.RunSynchronously ();
1132 Assert.IsTrue (onErrorTask.IsCompleted);
1133 Assert.IsFalse (onErrorTask.IsFaulted);
1134 Assert.IsFalse (continuationRan);
1138 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
1140 var continuationRan = false;
1141 AggregateException e = null;
1142 var testTask = new Task (() =>
1144 var child1 = new Task (() =>
1146 var child2 = new Task (() =>
1148 throw new InvalidOperationException();
1149 }, TaskCreationOptions.AttachedToParent);
1150 child2.RunSynchronously ();
1151 }, TaskCreationOptions.AttachedToParent);
1153 child1.RunSynchronously();
1154 e = child1.Exception;
1155 child1.Exception.Handle (ex => true);
1157 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1158 testTask.RunSynchronously ();
1159 onErrorTask.Wait (1000);
1160 Assert.IsNotNull (e);
1161 Assert.IsTrue (continuationRan);
1165 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1167 string result = "Failed";
1168 var testTask = new Task (() =>
1170 var child = new Task<string> (() =>
1173 }, TaskCreationOptions.AttachedToParent);
1174 child.RunSynchronously ();
1175 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1177 testTask.RunSynchronously ();
1179 Assert.AreEqual ("Success", result);
1183 public void InlineNotTrashingParentRelationship ()
1185 bool r1 = false, r2 = false;
1186 var t = new Task (() => {
1187 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1188 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1190 t.RunSynchronously ();
1197 public void AsyncWaitHandleSet ()
1199 var task = new TaskFactory ().StartNew (() => { });
1200 var ar = (IAsyncResult)task;
1201 Assert.IsFalse (ar.CompletedSynchronously, "#1");
1202 Assert.IsTrue (ar.AsyncWaitHandle.WaitOne (5000), "#2");
1206 public void StartOnBrokenScheduler ()
1208 var t = new Task (delegate { });
1211 t.Start (new ExceptionScheduler ());
1213 } catch (TaskSchedulerException e) {
1214 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1215 Assert.AreSame (e, t.Exception.InnerException, "#3");
1216 Assert.IsTrue (e.InnerException is ApplicationException, "#4");
1221 public void ContinuationOnBrokenScheduler ()
1223 var s = new ExceptionScheduler ();
1224 Task t = new Task(delegate {});
1226 var t2 = t.ContinueWith (delegate {
1227 }, TaskContinuationOptions.ExecuteSynchronously, s);
1229 var t3 = t.ContinueWith (delegate {
1230 }, TaskContinuationOptions.ExecuteSynchronously, s);
1235 Assert.IsTrue (t3.Wait (2000), "#0");
1237 } catch (AggregateException e) {
1240 Assert.AreEqual (TaskStatus.Faulted, t2.Status, "#2");
1241 Assert.AreEqual (TaskStatus.Faulted, t3.Status, "#3");
1245 public void Delay_Invalid ()
1249 } catch (ArgumentOutOfRangeException) {
1254 public void Delay_Start ()
1256 var t = Task.Delay (5000);
1259 } catch (InvalidOperationException) {
1264 public void Delay_Simple ()
1266 var t = Task.Delay (300);
1267 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1268 Assert.IsTrue (t.Wait (400), "#2");
1272 public void Delay_Cancelled ()
1274 var cancelation = new CancellationTokenSource ();
1276 var t = Task.Delay (5000, cancelation.Token);
1277 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1278 cancelation.Cancel ();
1282 } catch (AggregateException) {
1283 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1286 cancelation = new CancellationTokenSource ();
1287 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1288 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1289 cancelation.Cancel ();
1292 Assert.Fail ("#12");
1293 } catch (AggregateException) {
1294 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1299 public void Delay_TimeManagement ()
1301 var delay1 = Task.Delay(50);
1302 var delay2 = Task.Delay(25);
1303 Assert.IsTrue (Task.WhenAny(new[] { delay1, delay2 }).Wait (1000));
1304 Assert.AreEqual (TaskStatus.RanToCompletion, delay2.Status);
1308 public void WaitAny_WithNull ()
1310 var tasks = new [] {
1311 Task.FromResult (2),
1316 Task.WaitAny (tasks);
1318 } catch (ArgumentException) {
1323 public void WhenAll_Empty ()
1325 var tasks = new Task[0];
1327 Task t = Task.WhenAll(tasks);
1329 Assert.IsTrue(t.Wait(1000), "#1");
1333 public void WhenAll_WithNull ()
1336 Task.FromResult (2),
1341 Task.WhenAll (tasks);
1343 } catch (ArgumentException) {
1348 Task.WhenAll (tasks);
1350 } catch (ArgumentException) {
1355 public void WhenAll_Start ()
1357 Task[] tasks = new[] {
1358 Task.FromResult (2),
1361 var t = Task.WhenAll (tasks);
1362 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1367 } catch (InvalidOperationException) {
1371 new Task (delegate { }),
1374 t = Task.WhenAll (tasks);
1375 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1379 Assert.Fail ("#12");
1380 } catch (InvalidOperationException) {
1385 public void WhenAll_Cancelled ()
1387 var cancelation = new CancellationTokenSource ();
1388 var tasks = new Task[] {
1389 new Task (delegate { }),
1390 new Task (delegate { }, cancelation.Token)
1393 cancelation.Cancel ();
1395 var t = Task.WhenAll (tasks);
1396 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1400 Assert.IsTrue (t.Wait (1000), "#2");
1401 Assert.Fail ("#2a");
1402 } catch (AggregateException e) {
1403 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1408 public void WhenAll_Faulted ()
1410 var tcs = new TaskCompletionSource<object> ();
1411 tcs.SetException (new ApplicationException ());
1413 var tcs2 = new TaskCompletionSource<object> ();
1414 tcs2.SetException (new InvalidTimeZoneException ());
1416 var cancelation = new CancellationTokenSource ();
1417 var tasks = new Task[] {
1418 new Task (delegate { }),
1419 new Task (delegate { }, cancelation.Token),
1424 cancelation.Cancel ();
1426 var t = Task.WhenAll (tasks);
1427 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1431 Assert.IsTrue (t.Wait (1000), "#2");
1432 Assert.Fail ("#2a");
1433 } catch (AggregateException e) {
1434 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1435 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1440 public void WhenAll ()
1442 var t1 = new Task (delegate { });
1443 var t2 = new Task (delegate { t1.Start (); });
1445 var tasks = new Task[] {
1450 var t = Task.WhenAll (tasks);
1451 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1454 Assert.IsTrue (t.Wait (1000), "#2");
1458 public void WhenAllResult_Empty ()
1460 var tasks = new Task<int>[0];
1462 Task<int[]> t = Task.WhenAll(tasks);
1464 Assert.IsTrue(t.Wait(1000), "#1");
1465 Assert.IsNotNull(t.Result, "#2");
1466 Assert.AreEqual(t.Result.Length, 0, "#3");
1470 public void WhenAllResult_WithNull ()
1473 Task.FromResult (2),
1478 Task.WhenAll<int> (tasks);
1480 } catch (ArgumentException) {
1485 Task.WhenAll<int> (tasks);
1487 } catch (ArgumentException) {
1492 public void WhenAllResult_Cancelled ()
1494 var cancelation = new CancellationTokenSource ();
1495 var tasks = new [] {
1496 new Task<int> (delegate { return 9; }),
1497 new Task<int> (delegate { return 1; }, cancelation.Token)
1500 cancelation.Cancel ();
1502 var t = Task.WhenAll (tasks);
1503 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1507 Assert.IsTrue (t.Wait (1000), "#2");
1508 Assert.Fail ("#2a");
1509 } catch (AggregateException e) {
1510 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1516 } catch (AggregateException) {
1521 public void WhenAllResult ()
1523 var t1 = new Task<string> (delegate { return "a"; });
1524 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1526 var tasks = new [] {
1531 var t = Task.WhenAll<string> (tasks);
1532 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1535 Assert.IsTrue (t.Wait (1000), "#2");
1536 Assert.AreEqual (2, t.Result.Length, "#3");
1537 Assert.AreEqual ("a", t.Result[0], "#3a");
1538 Assert.AreEqual ("b", t.Result[1], "#3b");
1542 public void WhenAllResult_Completed ()
1545 Task.FromResult (1),
1549 var t = Task.WhenAll<int> (tasks);
1550 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1551 Assert.AreEqual (2, t.Result.Length, "#2");
1552 Assert.AreEqual (1, t.Result[0], "#2a");
1553 Assert.AreEqual (2, t.Result[1], "#2b");
1557 public void WhenAny_WithNull ()
1559 var tasks = new Task[] {
1560 Task.FromResult (2),
1565 Task.WhenAny (tasks);
1567 } catch (ArgumentException) {
1572 Task.WhenAny (tasks);
1574 } catch (ArgumentException) {
1578 Task.WhenAny (new Task[0]);
1580 } catch (ArgumentException) {
1585 public void WhenAny_Start ()
1587 Task[] tasks = new[] {
1588 Task.FromResult (2),
1591 var t = Task.WhenAny (tasks);
1592 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1597 } catch (InvalidOperationException) {
1601 new Task (delegate { }),
1604 t = Task.WhenAny (tasks);
1605 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1609 Assert.Fail ("#12");
1610 } catch (InvalidOperationException) {
1615 public void WhenAny_Cancelled ()
1617 var cancelation = new CancellationTokenSource ();
1618 var tasks = new Task[] {
1619 new Task (delegate { }),
1620 new Task (delegate { }, cancelation.Token)
1623 cancelation.Cancel ();
1625 var t = Task.WhenAny (tasks);
1626 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1629 Assert.IsTrue (t.Wait (1000), "#2");
1630 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1634 public void WhenAny_Faulted ()
1636 var tcs = new TaskCompletionSource<object> ();
1637 tcs.SetException (new ApplicationException ());
1639 var tcs2 = new TaskCompletionSource<object> ();
1640 tcs2.SetException (new InvalidTimeZoneException ());
1642 var cancelation = new CancellationTokenSource ();
1643 var tasks = new Task[] {
1644 new Task (delegate { }),
1646 new Task (delegate { }, cancelation.Token),
1650 cancelation.Cancel ();
1652 var t = Task.WhenAny (tasks);
1653 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1656 Assert.IsTrue (t.Wait (1000), "#2");
1657 Assert.IsNull (t.Exception, "#3");
1659 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1663 public void WhenAny ()
1665 var t1 = new Task (delegate { });
1666 var t2 = new Task (delegate { t1.Start (); });
1668 var tasks = new Task[] {
1673 var t = Task.WhenAny (tasks);
1674 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1677 Assert.IsTrue (t.Wait (1000), "#2");
1678 Assert.IsNotNull (t.Result, "#3");
1682 public void WhenAnyResult_WithNull ()
1684 var tasks = new [] {
1685 Task.FromResult (2),
1690 Task.WhenAny<int> (tasks);
1692 } catch (ArgumentException) {
1697 Task.WhenAny<int> (tasks);
1699 } catch (ArgumentException) {
1703 Task.WhenAny<short> (new Task<short>[0]);
1705 } catch (ArgumentException) {
1710 public void WhenAnyResult_Start ()
1713 Task.FromResult (2),
1716 var t = Task.WhenAny<int> (tasks);
1717 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1722 } catch (InvalidOperationException) {
1726 new Task<int> (delegate { return 55; }),
1729 t = Task.WhenAny<int> (tasks);
1730 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1734 Assert.Fail ("#12");
1735 } catch (InvalidOperationException) {
1740 public void WhenAnyResult_Cancelled ()
1742 var cancelation = new CancellationTokenSource ();
1743 var tasks = new [] {
1744 new Task<double> (delegate { return 1.1; }),
1745 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1748 cancelation.Cancel ();
1750 var t = Task.WhenAny<double> (tasks);
1751 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1754 Assert.IsTrue (t.Wait (1000), "#2");
1755 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1759 public void WhenAnyResult_Faulted ()
1761 var tcs = new TaskCompletionSource<object> ();
1762 tcs.SetException (new ApplicationException ());
1764 var tcs2 = new TaskCompletionSource<object> ();
1765 tcs2.SetException (new InvalidTimeZoneException ());
1767 var cancelation = new CancellationTokenSource ();
1768 var tasks = new Task<object>[] {
1769 new Task<object> (delegate { return null; }),
1771 new Task<object> (delegate { return ""; }, cancelation.Token),
1775 cancelation.Cancel ();
1777 var t = Task.WhenAny<object> (tasks);
1778 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1781 Assert.IsTrue (t.Wait (1000), "#2");
1782 Assert.IsNull (t.Exception, "#3");
1784 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1788 public void WhenAnyResult ()
1790 var t1 = new Task<byte> (delegate { return 3; });
1791 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1793 var tasks = new [] {
1798 var t = Task.WhenAny<byte> (tasks);
1799 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1802 Assert.IsTrue (t.Wait (1000), "#2");
1803 Assert.IsTrue (t.Result.Result > 1, "#3");
1807 public void ContinueWith_StateValue ()
1809 var t = Task.Factory.StartNew (l => {
1810 Assert.AreEqual (1, l, "a-1");
1813 var c = t.ContinueWith ((a, b) => {
1814 Assert.AreEqual (t, a, "c-1");
1815 Assert.AreEqual (2, b, "c-2");
1818 var d = t.ContinueWith ((a, b) => {
1819 Assert.AreEqual (t, a, "d-1");
1820 Assert.AreEqual (3, b, "d-2");
1824 Assert.IsTrue (d.Wait (1000), "#1");
1826 Assert.AreEqual (1, t.AsyncState, "#2");
1827 Assert.AreEqual (2, c.AsyncState, "#3");
1828 Assert.AreEqual (3, d.AsyncState, "#4");
1832 public void ContinueWith_StateValueGeneric ()
1834 var t = Task<int>.Factory.StartNew (l => {
1835 Assert.AreEqual (1, l, "a-1");
1839 var c = t.ContinueWith ((a, b) => {
1840 Assert.AreEqual (t, a, "c-1");
1841 Assert.AreEqual (2, b, "c-2");
1845 var d = t.ContinueWith ((a, b) => {
1846 Assert.AreEqual (t, a, "d-1");
1847 Assert.AreEqual (3, b, "d-2");
1851 Assert.IsTrue (d.Wait (1000), "#1");
1853 Assert.AreEqual (1, t.AsyncState, "#2");
1854 Assert.AreEqual (80, t.Result, "#2r");
1855 Assert.AreEqual (2, c.AsyncState, "#3");
1856 Assert.AreEqual ("c", c.Result, "#3r");
1857 Assert.AreEqual (3, d.AsyncState, "#4");
1858 Assert.AreEqual ('d', d.Result, "#3r");
1862 public void ContinueWith_CustomScheduleRejected ()
1864 var scheduler = new NonInlineableScheduler ();
1865 var t = Task.Factory.StartNew (delegate { }).
1866 ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
1868 Assert.IsTrue (t.Wait (5000));
1872 public void FromResult ()
1874 var t = Task.FromResult<object> (null);
1875 Assert.IsTrue (t.IsCompleted, "#1");
1876 Assert.AreEqual (null, t.Result, "#2");
1882 public void LongRunning ()
1886 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1888 Assert.IsTrue (t.Wait (5000), "#0");
1889 Assert.IsTrue ((bool)is_tp, "#1");
1890 Assert.IsTrue ((bool)is_bg, "#2");
1894 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1896 Assert.IsTrue (t.Wait (5000), "#10");
1897 Assert.IsFalse ((bool) is_tp, "#11");
1898 Assert.IsTrue ((bool) is_bg, "#12");
1902 public void Run_ArgumentCheck ()
1905 Task.Run (null as Action);
1907 } catch (ArgumentNullException) {
1914 bool ranOnDefaultScheduler = false;
1915 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1916 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1918 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1922 public void Run_Cancel ()
1924 var t = Task.Run (() => 1, new CancellationToken (true));
1928 } catch (AggregateException) {
1931 Assert.IsTrue (t.IsCanceled, "#2");
1935 public void Run_ExistingTaskT ()
1937 var t = new Task<int> (() => 5);
1938 var t2 = Task.Run (() => { t.Start (); return t; });
1940 Assert.IsTrue (t2.Wait (1000), "#1");
1941 Assert.AreEqual (5, t2.Result, "#2");
1945 public void Run_ExistingTask ()
1947 var t = new Task (delegate { throw new Exception ("Foo"); });
1948 var t2 = Task.Run (() => { t.Start (); return t; });
1953 } catch (Exception) {}
1955 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1959 public void DenyChildAttachTest ()
1961 var mre = new ManualResetEventSlim ();
1963 Task parent = Task.Factory.StartNew (() => {
1964 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1965 }, TaskCreationOptions.DenyChildAttach);
1966 Assert.IsTrue (parent.Wait (1000), "#1");
1968 Assert.IsTrue (nested.Wait (2000), "#2");
1971 class SynchronousScheduler : TaskScheduler
1973 protected override IEnumerable<Task> GetScheduledTasks ()
1975 throw new NotImplementedException ();
1978 protected override void QueueTask (Task task)
1980 TryExecuteTaskInline (task, false);
1983 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1985 return base.TryExecuteTask (task);
1990 public void HideSchedulerTest ()
1992 var mre = new ManualResetEventSlim ();
1993 var ranOnDefault = false;
1994 var scheduler = new SynchronousScheduler ();
1996 Task parent = Task.Factory.StartNew (() => {
1997 Task.Factory.StartNew (() => {
1998 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
2001 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
2003 Assert.IsTrue (mre.Wait (1000), "#1");
2004 Assert.IsTrue (ranOnDefault, "#2");
2008 public void LazyCancelationTest ()
2010 var source = new CancellationTokenSource ();
2012 var parent = new Task (delegate {});
2013 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
2015 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
2018 Assert.IsTrue (cont.Wait (1000), "#2");
2020 } catch (AggregateException ex) {
2021 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
2026 public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
2029 var child = Task.Factory.StartNew (() => {
2030 inner = Task.Run (() => {
2031 throw new ApplicationException ();
2032 }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
2036 var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
2037 Assert.IsTrue (t.Wait (5000), "#1");
2038 Assert.AreEqual (1, counter, "#2");
2039 Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
2040 Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
2044 [Category("NotWorking")]
2045 public void TaskContinuationChainLeak()
2047 // Start cranking out tasks, starting each new task upon completion of and from inside the prior task.
2049 var tester = new TaskContinuationChainLeakTester ();
2051 tester.TasksPilledUp.WaitOne ();
2053 // Head task should be out of scope by now. Manually run the GC and expect that it gets collected.
2056 GC.WaitForPendingFinalizers ();
2059 // It's important that we do the asserting while the task recursion is still going, since that is the
2060 // crux of the problem scenario.
2068 class TaskContinuationChainLeakTester
2070 volatile bool m_bStop;
2072 ManualResetEvent mre = new ManualResetEvent (false);
2073 WeakReference<Task> headTaskWeakRef;
2075 public ManualResetEvent TasksPilledUp {
2083 headTaskWeakRef = new WeakReference<Task> (StartNewTask ());
2086 public Task StartNewTask ()
2091 if (++counter == 50)
2094 return Task.Factory.StartNew (DummyWorker).ContinueWith (task => StartNewTask ());
2102 public void Verify ()
2105 Assert.IsFalse (headTaskWeakRef.TryGetTarget (out task));