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;
1059 var task = Task.Factory.StartNew (() => { Assert.IsTrue (evt.Wait (2000), "#1"); });
1060 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
1064 Assert.IsTrue (task.Wait (2000), "#2");
1066 Assert.IsFalse (cont.Wait (4000), "#3");
1067 } catch (AggregateException ex) {
1070 Assert.IsTrue (task.IsCompleted, "#4");
1071 Assert.IsTrue (cont.IsCanceled, "#5");
1072 Assert.IsFalse (result, "#6");
1076 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
1078 Task innerTask = null;
1079 var testTask = new Task (() =>
1081 innerTask = new Task (() =>
1083 throw new InvalidOperationException ();
1084 }, TaskCreationOptions.AttachedToParent);
1085 innerTask.RunSynchronously ();
1087 testTask.RunSynchronously ();
1089 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
1090 Assert.IsNotNull (innerTask);
1091 Assert.IsTrue (innerTask.IsFaulted);
1092 Assert.IsNotNull (testTask.Exception);
1093 Assert.IsTrue (testTask.IsFaulted);
1094 Assert.IsNotNull (innerTask.Exception);
1098 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
1100 var continuationRan = false;
1101 var testTask = new Task (() =>
1103 var task = new Task (() =>
1105 throw new InvalidOperationException();
1106 }, TaskCreationOptions.AttachedToParent);
1107 task.RunSynchronously ();
1109 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1110 testTask.RunSynchronously ();
1111 onErrorTask.Wait (100);
1112 Assert.IsTrue (continuationRan);
1116 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
1118 var continuationRan = false;
1119 var testTask = new Task (() =>
1121 var task = new Task (() =>
1123 throw new InvalidOperationException();
1124 }, TaskCreationOptions.AttachedToParent);
1125 task.RunSynchronously();
1127 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
1128 testTask.RunSynchronously ();
1129 Assert.IsTrue (onErrorTask.IsCompleted);
1130 Assert.IsFalse (onErrorTask.IsFaulted);
1131 Assert.IsFalse (continuationRan);
1135 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
1137 var continuationRan = false;
1138 AggregateException e = null;
1139 var testTask = new Task (() =>
1141 var child1 = new Task (() =>
1143 var child2 = new Task (() =>
1145 throw new InvalidOperationException();
1146 }, TaskCreationOptions.AttachedToParent);
1147 child2.RunSynchronously ();
1148 }, TaskCreationOptions.AttachedToParent);
1150 child1.RunSynchronously();
1151 e = child1.Exception;
1152 child1.Exception.Handle (ex => true);
1154 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1155 testTask.RunSynchronously ();
1156 onErrorTask.Wait (1000);
1157 Assert.IsNotNull (e);
1158 Assert.IsTrue (continuationRan);
1162 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1164 string result = "Failed";
1165 var testTask = new Task (() =>
1167 var child = new Task<string> (() =>
1170 }, TaskCreationOptions.AttachedToParent);
1171 child.RunSynchronously ();
1172 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1174 testTask.RunSynchronously ();
1176 Assert.AreEqual ("Success", result);
1180 public void InlineNotTrashingParentRelationship ()
1182 bool r1 = false, r2 = false;
1183 var t = new Task (() => {
1184 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1185 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1187 t.RunSynchronously ();
1194 public void AsyncWaitHandleSet ()
1196 var task = new TaskFactory ().StartNew (() => { });
1197 var ar = (IAsyncResult)task;
1198 Assert.IsFalse (ar.CompletedSynchronously, "#1");
1199 Assert.IsTrue (ar.AsyncWaitHandle.WaitOne (5000), "#2");
1203 public void StartOnBrokenScheduler ()
1205 var t = new Task (delegate { });
1208 t.Start (new ExceptionScheduler ());
1210 } catch (TaskSchedulerException e) {
1211 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1212 Assert.AreSame (e, t.Exception.InnerException, "#3");
1213 Assert.IsTrue (e.InnerException is ApplicationException, "#4");
1218 public void ContinuationOnBrokenScheduler ()
1220 var s = new ExceptionScheduler ();
1221 Task t = new Task(delegate {});
1223 var t2 = t.ContinueWith (delegate {
1224 }, TaskContinuationOptions.ExecuteSynchronously, s);
1226 var t3 = t.ContinueWith (delegate {
1227 }, TaskContinuationOptions.ExecuteSynchronously, s);
1232 Assert.IsTrue (t3.Wait (2000), "#0");
1234 } catch (AggregateException e) {
1237 Assert.AreEqual (TaskStatus.Faulted, t2.Status, "#2");
1238 Assert.AreEqual (TaskStatus.Faulted, t3.Status, "#3");
1242 public void Delay_Invalid ()
1246 } catch (ArgumentOutOfRangeException) {
1251 public void Delay_Start ()
1253 var t = Task.Delay (5000);
1256 } catch (InvalidOperationException) {
1261 public void Delay_Simple ()
1263 var t = Task.Delay (300);
1264 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1265 Assert.IsTrue (t.Wait (400), "#2");
1269 public void Delay_Cancelled ()
1271 var cancelation = new CancellationTokenSource ();
1273 var t = Task.Delay (5000, cancelation.Token);
1274 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1275 cancelation.Cancel ();
1279 } catch (AggregateException) {
1280 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1283 cancelation = new CancellationTokenSource ();
1284 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1285 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1286 cancelation.Cancel ();
1289 Assert.Fail ("#12");
1290 } catch (AggregateException) {
1291 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1296 public void Delay_TimeManagement ()
1298 var delay1 = Task.Delay(50);
1299 var delay2 = Task.Delay(25);
1300 Assert.IsTrue (Task.WhenAny(new[] { delay1, delay2 }).Wait (1000));
1301 Assert.AreEqual (TaskStatus.RanToCompletion, delay2.Status);
1305 public void WaitAny_WithNull ()
1307 var tasks = new [] {
1308 Task.FromResult (2),
1313 Task.WaitAny (tasks);
1315 } catch (ArgumentException) {
1320 public void WhenAll_Empty ()
1322 var tasks = new Task[0];
1324 Task t = Task.WhenAll(tasks);
1326 Assert.IsTrue(t.Wait(1000), "#1");
1330 public void WhenAll_WithNull ()
1333 Task.FromResult (2),
1338 Task.WhenAll (tasks);
1340 } catch (ArgumentException) {
1345 Task.WhenAll (tasks);
1347 } catch (ArgumentException) {
1352 public void WhenAll_Start ()
1354 Task[] tasks = new[] {
1355 Task.FromResult (2),
1358 var t = Task.WhenAll (tasks);
1359 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1364 } catch (InvalidOperationException) {
1368 new Task (delegate { }),
1371 t = Task.WhenAll (tasks);
1372 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1376 Assert.Fail ("#12");
1377 } catch (InvalidOperationException) {
1382 public void WhenAll_Cancelled ()
1384 var cancelation = new CancellationTokenSource ();
1385 var tasks = new Task[] {
1386 new Task (delegate { }),
1387 new Task (delegate { }, cancelation.Token)
1390 cancelation.Cancel ();
1392 var t = Task.WhenAll (tasks);
1393 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1397 Assert.IsTrue (t.Wait (1000), "#2");
1398 Assert.Fail ("#2a");
1399 } catch (AggregateException e) {
1400 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1405 public void WhenAll_Faulted ()
1407 var tcs = new TaskCompletionSource<object> ();
1408 tcs.SetException (new ApplicationException ());
1410 var tcs2 = new TaskCompletionSource<object> ();
1411 tcs2.SetException (new InvalidTimeZoneException ());
1413 var cancelation = new CancellationTokenSource ();
1414 var tasks = new Task[] {
1415 new Task (delegate { }),
1416 new Task (delegate { }, cancelation.Token),
1421 cancelation.Cancel ();
1423 var t = Task.WhenAll (tasks);
1424 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1428 Assert.IsTrue (t.Wait (1000), "#2");
1429 Assert.Fail ("#2a");
1430 } catch (AggregateException e) {
1431 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1432 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1437 public void WhenAll ()
1439 var t1 = new Task (delegate { });
1440 var t2 = new Task (delegate { t1.Start (); });
1442 var tasks = new Task[] {
1447 var t = Task.WhenAll (tasks);
1448 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1451 Assert.IsTrue (t.Wait (1000), "#2");
1455 public void WhenAllResult_Empty ()
1457 var tasks = new Task<int>[0];
1459 Task<int[]> t = Task.WhenAll(tasks);
1461 Assert.IsTrue(t.Wait(1000), "#1");
1462 Assert.IsNotNull(t.Result, "#2");
1463 Assert.AreEqual(t.Result.Length, 0, "#3");
1467 public void WhenAllResult_WithNull ()
1470 Task.FromResult (2),
1475 Task.WhenAll<int> (tasks);
1477 } catch (ArgumentException) {
1482 Task.WhenAll<int> (tasks);
1484 } catch (ArgumentException) {
1489 public void WhenAllResult_Cancelled ()
1491 var cancelation = new CancellationTokenSource ();
1492 var tasks = new [] {
1493 new Task<int> (delegate { return 9; }),
1494 new Task<int> (delegate { return 1; }, cancelation.Token)
1497 cancelation.Cancel ();
1499 var t = Task.WhenAll (tasks);
1500 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1504 Assert.IsTrue (t.Wait (1000), "#2");
1505 Assert.Fail ("#2a");
1506 } catch (AggregateException e) {
1507 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1513 } catch (AggregateException) {
1518 public void WhenAllResult ()
1520 var t1 = new Task<string> (delegate { return "a"; });
1521 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1523 var tasks = new [] {
1528 var t = Task.WhenAll<string> (tasks);
1529 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1532 Assert.IsTrue (t.Wait (1000), "#2");
1533 Assert.AreEqual (2, t.Result.Length, "#3");
1534 Assert.AreEqual ("a", t.Result[0], "#3a");
1535 Assert.AreEqual ("b", t.Result[1], "#3b");
1539 public void WhenAllResult_Completed ()
1542 Task.FromResult (1),
1546 var t = Task.WhenAll<int> (tasks);
1547 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1548 Assert.AreEqual (2, t.Result.Length, "#2");
1549 Assert.AreEqual (1, t.Result[0], "#2a");
1550 Assert.AreEqual (2, t.Result[1], "#2b");
1554 public void WhenAny_WithNull ()
1556 var tasks = new Task[] {
1557 Task.FromResult (2),
1562 Task.WhenAny (tasks);
1564 } catch (ArgumentException) {
1569 Task.WhenAny (tasks);
1571 } catch (ArgumentException) {
1575 Task.WhenAny (new Task[0]);
1577 } catch (ArgumentException) {
1582 public void WhenAny_Start ()
1584 Task[] tasks = new[] {
1585 Task.FromResult (2),
1588 var t = Task.WhenAny (tasks);
1589 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1594 } catch (InvalidOperationException) {
1598 new Task (delegate { }),
1601 t = Task.WhenAny (tasks);
1602 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1606 Assert.Fail ("#12");
1607 } catch (InvalidOperationException) {
1612 public void WhenAny_Cancelled ()
1614 var cancelation = new CancellationTokenSource ();
1615 var tasks = new Task[] {
1616 new Task (delegate { }),
1617 new Task (delegate { }, cancelation.Token)
1620 cancelation.Cancel ();
1622 var t = Task.WhenAny (tasks);
1623 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1626 Assert.IsTrue (t.Wait (1000), "#2");
1627 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1631 public void WhenAny_Faulted ()
1633 var tcs = new TaskCompletionSource<object> ();
1634 tcs.SetException (new ApplicationException ());
1636 var tcs2 = new TaskCompletionSource<object> ();
1637 tcs2.SetException (new InvalidTimeZoneException ());
1639 var cancelation = new CancellationTokenSource ();
1640 var tasks = new Task[] {
1641 new Task (delegate { }),
1643 new Task (delegate { }, cancelation.Token),
1647 cancelation.Cancel ();
1649 var t = Task.WhenAny (tasks);
1650 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1653 Assert.IsTrue (t.Wait (1000), "#2");
1654 Assert.IsNull (t.Exception, "#3");
1656 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1660 public void WhenAny ()
1662 var t1 = new Task (delegate { });
1663 var t2 = new Task (delegate { t1.Start (); });
1665 var tasks = new Task[] {
1670 var t = Task.WhenAny (tasks);
1671 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1674 Assert.IsTrue (t.Wait (1000), "#2");
1675 Assert.IsNotNull (t.Result, "#3");
1679 public void WhenAnyResult_WithNull ()
1681 var tasks = new [] {
1682 Task.FromResult (2),
1687 Task.WhenAny<int> (tasks);
1689 } catch (ArgumentException) {
1694 Task.WhenAny<int> (tasks);
1696 } catch (ArgumentException) {
1700 Task.WhenAny<short> (new Task<short>[0]);
1702 } catch (ArgumentException) {
1707 public void WhenAnyResult_Start ()
1710 Task.FromResult (2),
1713 var t = Task.WhenAny<int> (tasks);
1714 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1719 } catch (InvalidOperationException) {
1723 new Task<int> (delegate { return 55; }),
1726 t = Task.WhenAny<int> (tasks);
1727 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1731 Assert.Fail ("#12");
1732 } catch (InvalidOperationException) {
1737 public void WhenAnyResult_Cancelled ()
1739 var cancelation = new CancellationTokenSource ();
1740 var tasks = new [] {
1741 new Task<double> (delegate { return 1.1; }),
1742 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1745 cancelation.Cancel ();
1747 var t = Task.WhenAny<double> (tasks);
1748 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1751 Assert.IsTrue (t.Wait (1000), "#2");
1752 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1756 public void WhenAnyResult_Faulted ()
1758 var tcs = new TaskCompletionSource<object> ();
1759 tcs.SetException (new ApplicationException ());
1761 var tcs2 = new TaskCompletionSource<object> ();
1762 tcs2.SetException (new InvalidTimeZoneException ());
1764 var cancelation = new CancellationTokenSource ();
1765 var tasks = new Task<object>[] {
1766 new Task<object> (delegate { return null; }),
1768 new Task<object> (delegate { return ""; }, cancelation.Token),
1772 cancelation.Cancel ();
1774 var t = Task.WhenAny<object> (tasks);
1775 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1778 Assert.IsTrue (t.Wait (1000), "#2");
1779 Assert.IsNull (t.Exception, "#3");
1781 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1785 public void WhenAnyResult ()
1787 var t1 = new Task<byte> (delegate { return 3; });
1788 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1790 var tasks = new [] {
1795 var t = Task.WhenAny<byte> (tasks);
1796 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1799 Assert.IsTrue (t.Wait (1000), "#2");
1800 Assert.IsTrue (t.Result.Result > 1, "#3");
1804 public void ContinueWith_StateValue ()
1806 var t = Task.Factory.StartNew (l => {
1807 Assert.AreEqual (1, l, "a-1");
1810 var c = t.ContinueWith ((a, b) => {
1811 Assert.AreEqual (t, a, "c-1");
1812 Assert.AreEqual (2, b, "c-2");
1815 var d = t.ContinueWith ((a, b) => {
1816 Assert.AreEqual (t, a, "d-1");
1817 Assert.AreEqual (3, b, "d-2");
1821 Assert.IsTrue (d.Wait (1000), "#1");
1823 Assert.AreEqual (1, t.AsyncState, "#2");
1824 Assert.AreEqual (2, c.AsyncState, "#3");
1825 Assert.AreEqual (3, d.AsyncState, "#4");
1829 public void ContinueWith_StateValueGeneric ()
1831 var t = Task<int>.Factory.StartNew (l => {
1832 Assert.AreEqual (1, l, "a-1");
1836 var c = t.ContinueWith ((a, b) => {
1837 Assert.AreEqual (t, a, "c-1");
1838 Assert.AreEqual (2, b, "c-2");
1842 var d = t.ContinueWith ((a, b) => {
1843 Assert.AreEqual (t, a, "d-1");
1844 Assert.AreEqual (3, b, "d-2");
1848 Assert.IsTrue (d.Wait (1000), "#1");
1850 Assert.AreEqual (1, t.AsyncState, "#2");
1851 Assert.AreEqual (80, t.Result, "#2r");
1852 Assert.AreEqual (2, c.AsyncState, "#3");
1853 Assert.AreEqual ("c", c.Result, "#3r");
1854 Assert.AreEqual (3, d.AsyncState, "#4");
1855 Assert.AreEqual ('d', d.Result, "#3r");
1859 public void ContinueWith_CustomScheduleRejected ()
1861 var scheduler = new NonInlineableScheduler ();
1862 var t = Task.Factory.StartNew (delegate { }).
1863 ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
1865 Assert.IsTrue (t.Wait (5000));
1869 public void FromResult ()
1871 var t = Task.FromResult<object> (null);
1872 Assert.IsTrue (t.IsCompleted, "#1");
1873 Assert.AreEqual (null, t.Result, "#2");
1879 public void LongRunning ()
1883 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1885 Assert.IsTrue (t.Wait (5000), "#0");
1886 Assert.IsTrue ((bool)is_tp, "#1");
1887 Assert.IsTrue ((bool)is_bg, "#2");
1891 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1893 Assert.IsTrue (t.Wait (5000), "#10");
1894 Assert.IsFalse ((bool) is_tp, "#11");
1895 Assert.IsTrue ((bool) is_bg, "#12");
1899 public void Run_ArgumentCheck ()
1902 Task.Run (null as Action);
1904 } catch (ArgumentNullException) {
1911 bool ranOnDefaultScheduler = false;
1912 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1913 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1915 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1919 public void Run_Cancel ()
1921 var t = Task.Run (() => 1, new CancellationToken (true));
1925 } catch (AggregateException) {
1928 Assert.IsTrue (t.IsCanceled, "#2");
1932 public void Run_ExistingTaskT ()
1934 var t = new Task<int> (() => 5);
1935 var t2 = Task.Run (() => { t.Start (); return t; });
1937 Assert.IsTrue (t2.Wait (1000), "#1");
1938 Assert.AreEqual (5, t2.Result, "#2");
1942 public void Run_ExistingTask ()
1944 var t = new Task (delegate { throw new Exception ("Foo"); });
1945 var t2 = Task.Run (() => { t.Start (); return t; });
1950 } catch (Exception) {}
1952 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1956 public void DenyChildAttachTest ()
1958 var mre = new ManualResetEventSlim ();
1960 Task parent = Task.Factory.StartNew (() => {
1961 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1962 }, TaskCreationOptions.DenyChildAttach);
1963 Assert.IsTrue (parent.Wait (1000), "#1");
1965 Assert.IsTrue (nested.Wait (2000), "#2");
1968 class SynchronousScheduler : TaskScheduler
1970 protected override IEnumerable<Task> GetScheduledTasks ()
1972 throw new NotImplementedException ();
1975 protected override void QueueTask (Task task)
1977 TryExecuteTaskInline (task, false);
1980 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1982 return base.TryExecuteTask (task);
1987 public void HideSchedulerTest ()
1989 var mre = new ManualResetEventSlim ();
1990 var ranOnDefault = false;
1991 var scheduler = new SynchronousScheduler ();
1993 Task parent = Task.Factory.StartNew (() => {
1994 Task.Factory.StartNew (() => {
1995 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1998 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
2000 Assert.IsTrue (mre.Wait (1000), "#1");
2001 Assert.IsTrue (ranOnDefault, "#2");
2005 public void LazyCancelationTest ()
2007 var source = new CancellationTokenSource ();
2009 var parent = new Task (delegate {});
2010 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
2012 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
2015 Assert.IsTrue (cont.Wait (1000), "#2");
2017 } catch (AggregateException ex) {
2018 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
2023 public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
2026 var child = Task.Factory.StartNew (() => {
2027 inner = Task.Run (() => {
2028 throw new ApplicationException ();
2029 }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
2033 var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
2034 Assert.IsTrue (t.Wait (5000), "#1");
2035 Assert.AreEqual (1, counter, "#2");
2036 Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
2037 Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
2041 [Category("NotWorking")]
2042 public void TaskContinuationChainLeak()
2044 // Start cranking out tasks, starting each new task upon completion of and from inside the prior task.
2046 var tester = new TaskContinuationChainLeakTester ();
2048 tester.TasksPilledUp.WaitOne ();
2050 // Head task should be out of scope by now. Manually run the GC and expect that it gets collected.
2053 GC.WaitForPendingFinalizers ();
2056 // It's important that we do the asserting while the task recursion is still going, since that is the
2057 // crux of the problem scenario.
2065 class TaskContinuationChainLeakTester
2067 volatile bool m_bStop;
2069 ManualResetEvent mre = new ManualResetEvent (false);
2070 WeakReference<Task> headTaskWeakRef;
2072 public ManualResetEvent TasksPilledUp {
2080 headTaskWeakRef = new WeakReference<Task> (StartNewTask ());
2083 public Task StartNewTask ()
2088 if (++counter == 50)
2091 return Task.Factory.StartNew (DummyWorker).ContinueWith (task => StartNewTask ());
2099 public void Verify ()
2102 Assert.IsFalse (headTaskWeakRef.TryGetTarget (out task));