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;
37 namespace MonoTests.System.Threading.Tasks
40 public class TaskTests
42 class MockScheduler : TaskScheduler
44 public event Action<Task, bool> TryExecuteTaskInlineHandler;
46 protected override IEnumerable<Task> GetScheduledTasks ()
48 throw new NotImplementedException ();
51 protected override void QueueTask (Task task)
56 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
58 if (TryExecuteTaskInlineHandler != null)
59 TryExecuteTaskInlineHandler (task, taskWasPreviouslyQueued);
61 return base.TryExecuteTask (task);
65 class NonInlineableScheduler : TaskScheduler
67 protected override IEnumerable<Task> GetScheduledTasks ()
69 throw new NotImplementedException ();
72 protected override void QueueTask (Task task)
74 if (!base.TryExecuteTask (task))
75 throw new ApplicationException ();
78 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
84 class ExceptionScheduler : TaskScheduler
86 protected override IEnumerable<Task> GetScheduledTasks ()
88 throw new ApplicationException ("1");
91 protected override void QueueTask (Task task)
93 throw new ApplicationException ("2");
96 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
98 throw new ApplicationException ("3");
103 int completionPortThreads;
107 object cleanup_mutex = new object ();
108 List<Task> cleanup_list;
113 ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
114 ThreadPool.SetMinThreads (1, 1);
116 tasks = new Task[max];
117 cleanup_list = new List<Task> ();
121 public void Teardown()
123 ThreadPool.SetMinThreads (workerThreads, completionPortThreads);
125 lock (cleanup_mutex) {
126 l = cleanup_list.ToArray ();
130 } catch (Exception) {
134 void AddToCleanup (Task[] tasks) {
135 lock (cleanup_mutex) {
136 foreach (var t in tasks)
137 cleanup_list.Add (t);
141 void AddToCleanup (Task task) {
142 lock (cleanup_mutex) {
143 cleanup_list.Add (task);
147 void InitWithDelegate(Action action)
149 for (int i = 0; i < max; i++) {
150 tasks[i] = Task.Factory.StartNew(action);
152 AddToCleanup (tasks);
156 public void WaitAnyTest()
158 ParallelTestHelper.Repeat (delegate {
162 InitWithDelegate(delegate {
163 int times = Interlocked.Exchange (ref flag, 1);
165 SpinWait sw = new SpinWait ();
166 while (finished == 0) sw.SpinOnce ();
168 Interlocked.Increment (ref finished);
172 int index = Task.WaitAny(tasks, 1000);
174 Assert.AreNotEqual (-1, index, "#3");
175 Assert.AreEqual (1, flag, "#1");
176 Assert.AreEqual (1, finished, "#2");
181 public void WaitAny_Empty ()
183 Assert.AreEqual (-1, Task.WaitAny (new Task[0]));
187 public void WaitAny_Zero ()
189 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { })}, 0), "#1");
190 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { }) }, 20), "#1");
194 public void WaitAny_Cancelled ()
196 var cancelation = new CancellationTokenSource ();
197 var tasks = new Task[] {
198 new Task (delegate { }),
199 new Task (delegate { }, cancelation.Token)
202 cancelation.Cancel ();
204 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
205 Assert.IsTrue (tasks[1].IsCompleted, "#2");
206 Assert.IsTrue (tasks[1].IsCanceled, "#3");
210 public void WaitAny_CancelledWithoutExecution ()
212 var cancelation = new CancellationTokenSource ();
213 var tasks = new Task[] {
214 new Task (delegate { }),
215 new Task (delegate { })
219 var mre = new ManualResetEventSlim (false);
220 ThreadPool.QueueUserWorkItem (delegate {
221 res = Task.WaitAny (tasks, 20);
225 cancelation.Cancel ();
226 Assert.IsTrue (mre.Wait (1000), "#1");
227 Assert.AreEqual (-1, res);
231 public void WaitAny_OneException ()
233 var mre = new ManualResetEventSlim (false);
234 var tasks = new Task[] {
235 Task.Factory.StartNew (delegate { mre.Wait (5000); }),
236 Task.Factory.StartNew (delegate { throw new ApplicationException (); })
239 Assert.AreEqual (1, Task.WaitAny (tasks, 3000), "#1");
240 Assert.IsFalse (tasks[0].IsCompleted, "#2");
241 Assert.IsTrue (tasks[1].IsFaulted, "#3");
247 public void WaitAny_SingleCanceled ()
249 var src = new CancellationTokenSource ();
250 var t = Task.Factory.StartNew (() => { Thread.Sleep (200); src.Cancel (); src.Token.ThrowIfCancellationRequested (); }, src.Token);
251 Assert.AreEqual (0, Task.WaitAny (new [] { t }));
254 public void WaitAny_ManyExceptions ()
256 CountdownEvent cde = new CountdownEvent (3);
258 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
259 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
260 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
263 Assert.IsTrue (cde.Wait (1000), "#1");
266 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#2");
267 } catch (AggregateException e) {
268 Assert.AreEqual (3, e.InnerExceptions.Count, "#3");
273 public void WaitAny_ManyCanceled ()
275 var cancellation = new CancellationToken (true);
277 Task.Factory.StartNew (delegate { }, cancellation),
278 Task.Factory.StartNew (delegate { }, cancellation),
279 Task.Factory.StartNew (delegate { }, cancellation)
283 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#1");
284 } catch (AggregateException e) {
285 Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
290 public void WaitAllTest ()
292 ParallelTestHelper.Repeat (delegate {
294 InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
296 Assert.AreEqual(max, achieved, "#1");
301 public void WaitAll_ManyTasks ()
303 for (int r = 0; r < 2000; ++r) {
304 var tasks = new Task[60];
306 for (int i = 0; i < tasks.Length; i++) {
307 tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
309 AddToCleanup (tasks);
311 Assert.IsTrue (Task.WaitAll (tasks, 5000));
316 public void WaitAll_Zero ()
318 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 0), "#0");
319 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 10), "#1");
323 public void WaitAll_WithExceptions ()
325 InitWithDelegate (delegate { throw new ApplicationException (); });
328 Task.WaitAll (tasks);
330 } catch (AggregateException e) {
331 Assert.AreEqual (6, e.InnerExceptions.Count, "#2");
334 Assert.IsNotNull (tasks[0].Exception, "#3");
338 public void WaitAll_TimeoutWithExceptionsAfter ()
340 CountdownEvent cde = new CountdownEvent (2);
341 var mre = new ManualResetEvent (false);
343 Task.Factory.StartNew (delegate { Assert.IsTrue (mre.WaitOne (10000), "#0"); }),
344 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
345 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
348 Assert.IsTrue (cde.Wait (5000), "#1");
349 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
354 Task.WaitAll (tasks, 1000);
356 } catch (AggregateException e) {
357 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
362 public void WaitAll_TimeoutWithExceptionsBefore ()
364 CountdownEvent cde = new CountdownEvent (2);
365 var mre = new ManualResetEvent (false);
367 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
368 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
369 Task.Factory.StartNew (delegate { mre.WaitOne (); })
372 Assert.IsTrue (cde.Wait (1000), "#1");
373 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
378 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
380 } catch (AggregateException e) {
381 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
386 public void WaitAll_Cancelled ()
388 var cancelation = new CancellationTokenSource ();
389 var tasks = new Task[] {
390 new Task (delegate { cancelation.Cancel (); }),
391 new Task (delegate { }, cancelation.Token)
397 Task.WaitAll (tasks);
399 } catch (AggregateException e) {
400 var inner = (TaskCanceledException) e.InnerException;
401 Assert.AreEqual (tasks[1], inner.Task, "#2");
404 Assert.IsTrue (tasks[0].IsCompleted, "#3");
405 Assert.IsTrue (tasks[1].IsCanceled, "#4");
409 public void WaitAll_CancelledAndTimeout ()
411 var ct = new CancellationToken (true);
412 var t1 = new Task (() => {}, ct);
413 var t2 = Task.Delay (3000);
414 Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
418 public void WaitAllExceptionThenCancelled ()
420 var cancelation = new CancellationTokenSource ();
421 var tasks = new Task[] {
422 new Task (delegate { cancelation.Cancel (); throw new ApplicationException (); }),
423 new Task (delegate { }, cancelation.Token)
429 Task.WaitAll (tasks);
431 } catch (AggregateException e) {
432 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#2");
433 var inner = (TaskCanceledException) e.InnerExceptions[1];
434 Assert.AreEqual (tasks[1], inner.Task, "#3");
437 Assert.IsTrue (tasks[0].IsCompleted, "#4");
438 Assert.IsTrue (tasks[1].IsCanceled, "#5");
442 public void WaitAll_StartedUnderWait ()
444 var task1 = new Task (delegate { });
446 ThreadPool.QueueUserWorkItem (delegate {
447 // Sleep little to let task to start and hit internal wait
452 Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
456 public void CancelBeforeStart ()
458 var src = new CancellationTokenSource ();
460 Task t = new Task (delegate { }, src.Token);
462 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
467 } catch (InvalidOperationException) {
472 public void Wait_CancelledTask ()
474 var src = new CancellationTokenSource ();
476 Task t = new Task (delegate { }, src.Token);
482 } catch (AggregateException e) {
483 var details = (TaskCanceledException) e.InnerException;
484 Assert.AreEqual (t, details.Task, "#1e");
490 } catch (AggregateException e) {
491 var details = (TaskCanceledException) e.InnerException;
492 Assert.AreEqual (t, details.Task, "#2e");
493 Assert.IsNull (details.Task.Exception, "#2e2");
498 public void Wait_Inlined ()
500 bool? previouslyQueued = null;
502 var scheduler = new MockScheduler ();
503 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
504 previouslyQueued = b;
507 var tf = new TaskFactory (scheduler);
508 var t = tf.StartNew (() => { });
511 Assert.AreEqual (true, previouslyQueued);
515 public void CreationWhileInitiallyCanceled ()
517 var token = new CancellationToken (true);
518 var task = new Task (() => { }, token);
523 } catch (InvalidOperationException) {
529 } catch (AggregateException e) {
530 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
533 Assert.IsTrue (task.IsCanceled, "#4");
537 public void ContinueWithInvalidArguments ()
539 var task = new Task (() => { });
541 task.ContinueWith (null);
543 } catch (ArgumentNullException e) {
547 task.ContinueWith (delegate { }, null);
549 } catch (ArgumentNullException e) {
553 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
555 } catch (ArgumentOutOfRangeException) {
559 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
561 } catch (ArgumentOutOfRangeException) {
566 public void ContinueWithOnAnyTestCase()
568 ParallelTestHelper.Repeat (delegate {
571 Task t = Task.Factory.StartNew(delegate { });
572 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
573 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
574 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
575 Assert.IsNull(cont.Exception, "#1");
576 Assert.IsNotNull(cont, "#2");
577 Assert.IsTrue(result, "#3");
582 public void ContinueWithOnCompletedSuccessfullyTestCase()
584 ParallelTestHelper.Repeat (delegate {
587 Task t = Task.Factory.StartNew(delegate { });
588 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
589 Assert.IsTrue (t.Wait(1000), "#4");
590 Assert.IsTrue (cont.Wait(1000), "#5");
592 Assert.IsNull(cont.Exception, "#1");
593 Assert.IsNotNull(cont, "#2");
594 Assert.IsTrue(result, "#3");
599 public void ContinueWithOnAbortedTestCase()
602 bool taskResult = false;
604 CancellationTokenSource src = new CancellationTokenSource ();
605 Task t = new Task (delegate { taskResult = true; }, src.Token);
607 Task cont = t.ContinueWith (delegate { result = true; },
608 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
612 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
613 Assert.IsTrue (cont.IsCompleted, "#1b");
614 Assert.IsTrue (result, "#1c");
619 } catch (InvalidOperationException) {
622 Assert.IsTrue (cont.Wait (1000), "#3");
624 Assert.IsFalse (taskResult, "#4");
626 Assert.IsNull (cont.Exception, "#5");
627 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
631 public void ContinueWithOnFailedTestCase()
633 ParallelTestHelper.Repeat (delegate {
636 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
637 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
639 Assert.IsTrue (cont.Wait(1000), "#0");
640 Assert.IsNotNull (t.Exception, "#1");
641 Assert.IsNotNull (cont, "#2");
642 Assert.IsTrue (result, "#3");
647 public void ContinueWithWithStart ()
649 Task t = new Task<int> (() => 1);
650 t = t.ContinueWith (l => { });
654 } catch (InvalidOperationException) {
659 public void ContinueWithChildren ()
661 ParallelTestHelper.Repeat (delegate {
664 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
666 var mre = new ManualResetEvent (false);
667 t.ContinueWith (l => {
672 Assert.IsTrue (mre.WaitOne (1000), "#1");
673 Assert.IsTrue (result, "#2");
678 public void ContinueWithDifferentOptionsAreCanceledTest ()
680 var mre = new ManualResetEventSlim ();
681 var task = Task.Factory.StartNew (() => mre.Wait (200));
682 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
683 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
684 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
687 contSuccess.Wait (100);
689 Assert.IsTrue (contSuccess.IsCompleted);
690 Assert.IsTrue (contFailed.IsCompleted);
691 Assert.IsTrue (contCanceled.IsCompleted);
692 Assert.IsFalse (contSuccess.IsCanceled);
693 Assert.IsTrue (contFailed.IsCanceled);
694 Assert.IsTrue (contCanceled.IsCanceled);
698 public void MultipleTasks()
700 ParallelTestHelper.Repeat (delegate {
701 bool r1 = false, r2 = false, r3 = false;
703 Task t1 = Task.Factory.StartNew(delegate {
706 Task t2 = Task.Factory.StartNew(delegate {
709 Task t3 = Task.Factory.StartNew(delegate {
717 Assert.IsTrue(r1, "#1");
718 Assert.IsTrue(r2, "#2");
719 Assert.IsTrue(r3, "#3");
724 public void WaitChildTestCase()
726 ParallelTestHelper.Repeat (delegate {
727 bool r1 = false, r2 = false, r3 = false;
728 var mre = new ManualResetEventSlim (false);
729 var mreStart = new ManualResetEventSlim (false);
731 Task t = Task.Factory.StartNew(delegate {
732 Task.Factory.StartNew(delegate {
735 }, TaskCreationOptions.AttachedToParent);
736 Task.Factory.StartNew(delegate {
738 }, TaskCreationOptions.AttachedToParent);
739 Task.Factory.StartNew(delegate {
741 }, TaskCreationOptions.AttachedToParent);
746 Assert.IsFalse (t.Wait (10), "#0a");
748 Assert.IsTrue (t.Wait (500), "#0b");
749 Assert.IsTrue(r2, "#1");
750 Assert.IsTrue(r3, "#2");
751 Assert.IsTrue(r1, "#3");
752 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
759 public void WaitingForChildrenToComplete ()
762 var mre = new ManualResetEvent (false);
764 parent_wfc = Task.Factory.StartNew (() => {
765 nested = Task.Factory.StartNew (() => {
766 Assert.IsTrue (mre.WaitOne (4000), "parent_wfc needs to be set first");
767 Assert.IsFalse (parent_wfc.Wait (10), "#1a");
768 Assert.AreEqual (TaskStatus.WaitingForChildrenToComplete, parent_wfc.Status, "#1b");
769 }, TaskCreationOptions.AttachedToParent).ContinueWith (l => {
770 Assert.IsTrue (parent_wfc.Wait (2000), "#2a");
771 Assert.AreEqual (TaskStatus.RanToCompletion, parent_wfc.Status, "#2b");
772 }, TaskContinuationOptions.ExecuteSynchronously);
776 Assert.IsTrue (parent_wfc.Wait (2000), "#3");
777 Assert.IsTrue (nested.Wait (2000), "#4");
781 public void WaitChildWithContinuationAttachedTest ()
784 var task = new Task(() =>
786 Task.Factory.StartNew(() => {
788 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
791 }, TaskContinuationOptions.AttachedToParent);
795 Assert.IsTrue (result);
799 public void WaitChildWithContinuationNotAttachedTest ()
801 var task = new Task(() =>
803 Task.Factory.StartNew(() => {
805 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
810 Assert.IsTrue (task.Wait(400));
814 public void WaitChildWithNesting ()
817 var t = Task.Factory.StartNew (() => {
818 Task.Factory.StartNew (() => {
819 Task.Factory.StartNew (() => {
822 }, TaskCreationOptions.AttachedToParent);
823 }, TaskCreationOptions.AttachedToParent);
825 Assert.IsTrue (t.Wait (4000), "#1");
826 Assert.IsTrue (result, "#2");
830 public void DoubleWaitTest ()
832 ParallelTestHelper.Repeat (delegate {
833 var evt = new ManualResetEventSlim ();
834 var monitor = new object ();
836 var t = Task.Factory.StartNew (delegate {
837 var r = evt.Wait (5000);
840 Monitor.Pulse (monitor);
842 return r ? 1 : 10; //1 -> ok, 10 -> evt wait failed
844 var cntd = new CountdownEvent (2);
845 var cntd2 = new CountdownEvent (2);
848 ThreadPool.QueueUserWorkItem (delegate {
851 r1 = 20; // 20 -> task wait failed
852 else if (t.Result != 1)
853 r1 = 30 + t.Result; // 30 -> task result is bad
859 Monitor.Pulse (monitor);
862 ThreadPool.QueueUserWorkItem (delegate {
865 r2 = 40; // 40 -> task wait failed
866 else if (t.Result != 1)
867 r2 = 50 + t.Result; // 50 -> task result is bad
874 Monitor.Pulse (monitor);
877 Assert.IsTrue (cntd.Wait (4000), "#1");
879 Assert.IsTrue (cntd2.Wait (4000), "#2");
880 Assert.AreEqual (2, r1, "r1");
881 Assert.AreEqual (3, r2, "r2");
883 // Wait for everything to finish to avoid overloading the tpool
889 Monitor.Wait (monitor);
896 public void DoubleTimeoutedWaitTest ()
898 var evt = new ManualResetEventSlim ();
899 var t = new Task (delegate { });
900 var cntd = new CountdownEvent (2);
902 bool r1 = false, r2 = false;
903 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
904 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
912 public void RunSynchronously ()
915 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
916 t.RunSynchronously ();
918 Assert.AreEqual (1, val, "#1");
920 t = new Task (() => { Thread.Sleep (0); val = 2; });
922 bool? previouslyQueued = null;
924 var scheduler = new MockScheduler ();
925 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
926 previouslyQueued = b;
929 t.RunSynchronously (scheduler);
931 Assert.AreEqual (2, val, "#2");
932 Assert.AreEqual (false, previouslyQueued, "#2a");
936 public void RunSynchronouslyArgumentChecks ()
938 Task t = new Task (() => { });
940 t.RunSynchronously (null);
942 } catch (ArgumentNullException) {
947 public void RunSynchronously_SchedulerException ()
949 var scheduler = new MockScheduler ();
950 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
951 throw new ApplicationException ();
954 Task t = new Task (() => { });
956 t.RunSynchronously (scheduler);
958 } catch (Exception e) {
959 Assert.AreEqual (t.Exception.InnerException, e);
964 public void RunSynchronouslyWithAttachedChildren ()
967 var t = new Task (() => {
968 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
970 t.RunSynchronously ();
971 Assert.IsTrue (result);
975 public void RunSynchronouslyOnContinuation ()
977 Task t = new Task<int> (() => 1);
978 t = t.ContinueWith (l => { });
980 t.RunSynchronously ();
982 } catch (InvalidOperationException) {
987 public void UnobservedExceptionOnFinalizerThreadTest ()
989 bool wasCalled = false;
990 TaskScheduler.UnobservedTaskException += (o, args) => {
994 var inner = new ApplicationException ();
995 Thread t = new Thread (delegate () {
996 Task.Factory.StartNew (() => { throw inner; });
1000 Thread.Sleep (1000);
1002 Thread.Sleep (1000);
1003 GC.WaitForPendingFinalizers ();
1005 Assert.IsTrue (wasCalled);
1008 [Test, ExpectedException (typeof (InvalidOperationException))]
1009 public void StartFinishedTaskTest ()
1011 var t = Task.Factory.StartNew (delegate () { });
1018 public void Start_NullArgument ()
1020 var t = new Task (() => { });
1024 } catch (ArgumentNullException) {
1028 [Test, ExpectedException (typeof (InvalidOperationException))]
1029 public void DisposeUnstartedTest ()
1031 var t = new Task (() => { });
1036 public void ThrowingUnrelatedCanceledExceptionTest ()
1038 Task t = new Task (() => {
1039 throw new TaskCanceledException ();
1042 t.RunSynchronously ();
1043 Assert.IsTrue (t.IsFaulted);
1044 Assert.IsFalse (t.IsCanceled);
1048 public void CanceledContinuationExecuteSynchronouslyTest ()
1050 var source = new CancellationTokenSource();
1051 var token = source.Token;
1052 var evt = new ManualResetEventSlim ();
1053 bool result = false;
1055 var task = Task.Factory.StartNew (() => { Assert.IsTrue (evt.Wait (2000), "#1"); });
1056 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
1060 Assert.IsTrue (task.Wait (2000), "#2");
1062 Assert.IsFalse (cont.Wait (4000), "#3");
1063 } catch (AggregateException ex) {
1066 Assert.IsTrue (task.IsCompleted, "#4");
1067 Assert.IsTrue (cont.IsCanceled, "#5");
1068 Assert.IsFalse (result, "#6");
1072 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
1074 Task innerTask = null;
1075 var testTask = new Task (() =>
1077 innerTask = new Task (() =>
1079 throw new InvalidOperationException ();
1080 }, TaskCreationOptions.AttachedToParent);
1081 innerTask.RunSynchronously ();
1083 testTask.RunSynchronously ();
1085 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
1086 Assert.IsNotNull (innerTask);
1087 Assert.IsTrue (innerTask.IsFaulted);
1088 Assert.IsNotNull (testTask.Exception);
1089 Assert.IsTrue (testTask.IsFaulted);
1090 Assert.IsNotNull (innerTask.Exception);
1094 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
1096 var continuationRan = false;
1097 var testTask = new Task (() =>
1099 var task = new Task (() =>
1101 throw new InvalidOperationException();
1102 }, TaskCreationOptions.AttachedToParent);
1103 task.RunSynchronously ();
1105 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1106 testTask.RunSynchronously ();
1107 onErrorTask.Wait (100);
1108 Assert.IsTrue (continuationRan);
1112 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
1114 var continuationRan = false;
1115 var testTask = new Task (() =>
1117 var task = new Task (() =>
1119 throw new InvalidOperationException();
1120 }, TaskCreationOptions.AttachedToParent);
1121 task.RunSynchronously();
1123 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
1124 testTask.RunSynchronously ();
1125 Assert.IsTrue (onErrorTask.IsCompleted);
1126 Assert.IsFalse (onErrorTask.IsFaulted);
1127 Assert.IsFalse (continuationRan);
1131 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
1133 var continuationRan = false;
1134 AggregateException e = null;
1135 var testTask = new Task (() =>
1137 var child1 = new Task (() =>
1139 var child2 = new Task (() =>
1141 throw new InvalidOperationException();
1142 }, TaskCreationOptions.AttachedToParent);
1143 child2.RunSynchronously ();
1144 }, TaskCreationOptions.AttachedToParent);
1146 child1.RunSynchronously();
1147 e = child1.Exception;
1148 child1.Exception.Handle (ex => true);
1150 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1151 testTask.RunSynchronously ();
1152 onErrorTask.Wait (1000);
1153 Assert.IsNotNull (e);
1154 Assert.IsTrue (continuationRan);
1158 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1160 string result = "Failed";
1161 var testTask = new Task (() =>
1163 var child = new Task<string> (() =>
1166 }, TaskCreationOptions.AttachedToParent);
1167 child.RunSynchronously ();
1168 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1170 testTask.RunSynchronously ();
1172 Assert.AreEqual ("Success", result);
1176 public void InlineNotTrashingParentRelationship ()
1178 bool r1 = false, r2 = false;
1179 var t = new Task (() => {
1180 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1181 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1183 t.RunSynchronously ();
1190 public void AsyncWaitHandleSet ()
1192 var task = new TaskFactory ().StartNew (() => { });
1193 var ar = (IAsyncResult)task;
1194 Assert.IsFalse (ar.CompletedSynchronously, "#1");
1195 Assert.IsTrue (ar.AsyncWaitHandle.WaitOne (5000), "#2");
1199 public void StartOnBrokenScheduler ()
1201 var t = new Task (delegate { });
1204 t.Start (new ExceptionScheduler ());
1206 } catch (TaskSchedulerException e) {
1207 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1208 Assert.AreSame (e, t.Exception.InnerException, "#3");
1209 Assert.IsTrue (e.InnerException is ApplicationException, "#4");
1214 public void ContinuationOnBrokenScheduler ()
1216 var s = new ExceptionScheduler ();
1217 Task t = new Task(delegate {});
1219 var t2 = t.ContinueWith (delegate {
1220 }, TaskContinuationOptions.ExecuteSynchronously, s);
1222 var t3 = t.ContinueWith (delegate {
1223 }, TaskContinuationOptions.ExecuteSynchronously, s);
1228 Assert.IsTrue (t3.Wait (2000), "#0");
1230 } catch (AggregateException e) {
1233 Assert.AreEqual (TaskStatus.Faulted, t2.Status, "#2");
1234 Assert.AreEqual (TaskStatus.Faulted, t3.Status, "#3");
1238 public void Delay_Invalid ()
1242 } catch (ArgumentOutOfRangeException) {
1247 public void Delay_Start ()
1249 var t = Task.Delay (5000);
1252 } catch (InvalidOperationException) {
1257 public void Delay_Simple ()
1259 var t = Task.Delay (300);
1260 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1261 Assert.IsTrue (t.Wait (1200), "#2");
1265 public void Delay_Cancelled ()
1267 var cancelation = new CancellationTokenSource ();
1269 var t = Task.Delay (5000, cancelation.Token);
1270 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1271 cancelation.Cancel ();
1275 } catch (AggregateException) {
1276 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1279 cancelation = new CancellationTokenSource ();
1280 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1281 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1282 cancelation.Cancel ();
1285 Assert.Fail ("#12");
1286 } catch (AggregateException) {
1287 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1292 public void Delay_TimeManagement ()
1294 var delay1 = Task.Delay(50);
1295 var delay2 = Task.Delay(25);
1296 Assert.IsTrue (Task.WhenAny(new[] { delay1, delay2 }).Wait (1000));
1297 Assert.AreEqual (TaskStatus.RanToCompletion, delay2.Status);
1301 public void WaitAny_WithNull ()
1303 var tasks = new [] {
1304 Task.FromResult (2),
1309 Task.WaitAny (tasks);
1311 } catch (ArgumentException) {
1316 public void WhenAll_Empty ()
1318 var tasks = new Task[0];
1320 Task t = Task.WhenAll(tasks);
1322 Assert.IsTrue(t.Wait(1000), "#1");
1326 public void WhenAll_WithNull ()
1329 Task.FromResult (2),
1334 Task.WhenAll (tasks);
1336 } catch (ArgumentException) {
1341 Task.WhenAll (tasks);
1343 } catch (ArgumentException) {
1348 public void WhenAll_Start ()
1350 Task[] tasks = new[] {
1351 Task.FromResult (2),
1354 var t = Task.WhenAll (tasks);
1355 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1360 } catch (InvalidOperationException) {
1364 new Task (delegate { }),
1367 t = Task.WhenAll (tasks);
1368 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1372 Assert.Fail ("#12");
1373 } catch (InvalidOperationException) {
1378 public void WhenAll_Cancelled ()
1380 var cancelation = new CancellationTokenSource ();
1381 var tasks = new Task[] {
1382 new Task (delegate { }),
1383 new Task (delegate { }, cancelation.Token)
1386 cancelation.Cancel ();
1388 var t = Task.WhenAll (tasks);
1389 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1393 Assert.IsTrue (t.Wait (1000), "#2");
1394 Assert.Fail ("#2a");
1395 } catch (AggregateException e) {
1396 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1401 public void WhenAll_Faulted ()
1403 var tcs = new TaskCompletionSource<object> ();
1404 tcs.SetException (new ApplicationException ());
1406 var tcs2 = new TaskCompletionSource<object> ();
1407 tcs2.SetException (new InvalidTimeZoneException ());
1409 var cancelation = new CancellationTokenSource ();
1410 var tasks = new Task[] {
1411 new Task (delegate { }),
1412 new Task (delegate { }, cancelation.Token),
1417 cancelation.Cancel ();
1419 var t = Task.WhenAll (tasks);
1420 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1424 Assert.IsTrue (t.Wait (1000), "#2");
1425 Assert.Fail ("#2a");
1426 } catch (AggregateException e) {
1427 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1428 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1433 public void WhenAll ()
1435 var t1 = new Task (delegate { });
1436 var t2 = new Task (delegate { t1.Start (); });
1438 var tasks = new Task[] {
1443 var t = Task.WhenAll (tasks);
1444 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1447 Assert.IsTrue (t.Wait (1000), "#2");
1451 public void WhenAllResult_Empty ()
1453 var tasks = new Task<int>[0];
1455 Task<int[]> t = Task.WhenAll(tasks);
1457 Assert.IsTrue(t.Wait(1000), "#1");
1458 Assert.IsNotNull(t.Result, "#2");
1459 Assert.AreEqual(t.Result.Length, 0, "#3");
1463 public void WhenAllResult_WithNull ()
1466 Task.FromResult (2),
1471 Task.WhenAll<int> (tasks);
1473 } catch (ArgumentException) {
1478 Task.WhenAll<int> (tasks);
1480 } catch (ArgumentException) {
1485 public void WhenAllResult_Cancelled ()
1487 var cancelation = new CancellationTokenSource ();
1488 var tasks = new [] {
1489 new Task<int> (delegate { return 9; }),
1490 new Task<int> (delegate { return 1; }, cancelation.Token)
1493 cancelation.Cancel ();
1495 var t = Task.WhenAll (tasks);
1496 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1500 Assert.IsTrue (t.Wait (1000), "#2");
1501 Assert.Fail ("#2a");
1502 } catch (AggregateException e) {
1503 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1509 } catch (AggregateException) {
1514 public void WhenAllResult ()
1516 var t1 = new Task<string> (delegate { return "a"; });
1517 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1519 var tasks = new [] {
1524 var t = Task.WhenAll<string> (tasks);
1525 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1528 Assert.IsTrue (t.Wait (1000), "#2");
1529 Assert.AreEqual (2, t.Result.Length, "#3");
1530 Assert.AreEqual ("a", t.Result[0], "#3a");
1531 Assert.AreEqual ("b", t.Result[1], "#3b");
1535 public void WhenAllResult_Completed ()
1538 Task.FromResult (1),
1542 var t = Task.WhenAll<int> (tasks);
1543 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1544 Assert.AreEqual (2, t.Result.Length, "#2");
1545 Assert.AreEqual (1, t.Result[0], "#2a");
1546 Assert.AreEqual (2, t.Result[1], "#2b");
1550 public void WhenAny_WithNull ()
1552 var tasks = new Task[] {
1553 Task.FromResult (2),
1558 Task.WhenAny (tasks);
1560 } catch (ArgumentException) {
1565 Task.WhenAny (tasks);
1567 } catch (ArgumentException) {
1571 Task.WhenAny (new Task[0]);
1573 } catch (ArgumentException) {
1578 public void WhenAny_Start ()
1580 Task[] tasks = new[] {
1581 Task.FromResult (2),
1584 var t = Task.WhenAny (tasks);
1585 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1590 } catch (InvalidOperationException) {
1594 new Task (delegate { }),
1597 t = Task.WhenAny (tasks);
1598 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1602 Assert.Fail ("#12");
1603 } catch (InvalidOperationException) {
1608 public void WhenAny_Cancelled ()
1610 var cancelation = new CancellationTokenSource ();
1611 var tasks = new Task[] {
1612 new Task (delegate { }),
1613 new Task (delegate { }, cancelation.Token)
1616 cancelation.Cancel ();
1618 var t = Task.WhenAny (tasks);
1619 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1622 Assert.IsTrue (t.Wait (1000), "#2");
1623 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1627 public void WhenAny_Faulted ()
1629 var tcs = new TaskCompletionSource<object> ();
1630 tcs.SetException (new ApplicationException ());
1632 var tcs2 = new TaskCompletionSource<object> ();
1633 tcs2.SetException (new InvalidTimeZoneException ());
1635 var cancelation = new CancellationTokenSource ();
1636 var tasks = new Task[] {
1637 new Task (delegate { }),
1639 new Task (delegate { }, cancelation.Token),
1643 cancelation.Cancel ();
1645 var t = Task.WhenAny (tasks);
1646 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1649 Assert.IsTrue (t.Wait (1000), "#2");
1650 Assert.IsNull (t.Exception, "#3");
1652 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1656 public void WhenAny ()
1658 var t1 = new Task (delegate { });
1659 var t2 = new Task (delegate { t1.Start (); });
1661 var tasks = new Task[] {
1666 var t = Task.WhenAny (tasks);
1667 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1670 Assert.IsTrue (t.Wait (1000), "#2");
1671 Assert.IsNotNull (t.Result, "#3");
1675 public void WhenAnyResult_WithNull ()
1677 var tasks = new [] {
1678 Task.FromResult (2),
1683 Task.WhenAny<int> (tasks);
1685 } catch (ArgumentException) {
1690 Task.WhenAny<int> (tasks);
1692 } catch (ArgumentException) {
1696 Task.WhenAny<short> (new Task<short>[0]);
1698 } catch (ArgumentException) {
1703 public void WhenAnyResult_Start ()
1706 Task.FromResult (2),
1709 var t = Task.WhenAny<int> (tasks);
1710 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1715 } catch (InvalidOperationException) {
1719 new Task<int> (delegate { return 55; }),
1722 t = Task.WhenAny<int> (tasks);
1723 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1727 Assert.Fail ("#12");
1728 } catch (InvalidOperationException) {
1733 public void WhenAnyResult_Cancelled ()
1735 var cancelation = new CancellationTokenSource ();
1736 var tasks = new [] {
1737 new Task<double> (delegate { return 1.1; }),
1738 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1741 cancelation.Cancel ();
1743 var t = Task.WhenAny<double> (tasks);
1744 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1747 Assert.IsTrue (t.Wait (1000), "#2");
1748 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1752 public void WhenAnyResult_Faulted ()
1754 var tcs = new TaskCompletionSource<object> ();
1755 tcs.SetException (new ApplicationException ());
1757 var tcs2 = new TaskCompletionSource<object> ();
1758 tcs2.SetException (new InvalidTimeZoneException ());
1760 var cancelation = new CancellationTokenSource ();
1761 var tasks = new Task<object>[] {
1762 new Task<object> (delegate { return null; }),
1764 new Task<object> (delegate { return ""; }, cancelation.Token),
1768 cancelation.Cancel ();
1770 var t = Task.WhenAny<object> (tasks);
1771 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1774 Assert.IsTrue (t.Wait (1000), "#2");
1775 Assert.IsNull (t.Exception, "#3");
1777 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1781 public void WhenAnyResult ()
1783 var t1 = new Task<byte> (delegate { return 3; });
1784 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1786 var tasks = new [] {
1791 var t = Task.WhenAny<byte> (tasks);
1792 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1795 Assert.IsTrue (t.Wait (1000), "#2");
1796 Assert.IsTrue (t.Result.Result > 1, "#3");
1800 public void ContinueWith_StateValue ()
1802 var t = Task.Factory.StartNew (l => {
1803 Assert.AreEqual (1, l, "a-1");
1806 var c = t.ContinueWith ((a, b) => {
1807 Assert.AreEqual (t, a, "c-1");
1808 Assert.AreEqual (2, b, "c-2");
1811 var d = t.ContinueWith ((a, b) => {
1812 Assert.AreEqual (t, a, "d-1");
1813 Assert.AreEqual (3, b, "d-2");
1817 Assert.IsTrue (d.Wait (1000), "#1");
1819 Assert.AreEqual (1, t.AsyncState, "#2");
1820 Assert.AreEqual (2, c.AsyncState, "#3");
1821 Assert.AreEqual (3, d.AsyncState, "#4");
1825 public void ContinueWith_StateValueGeneric ()
1827 var t = Task<int>.Factory.StartNew (l => {
1828 Assert.AreEqual (1, l, "a-1");
1832 var c = t.ContinueWith ((a, b) => {
1833 Assert.AreEqual (t, a, "c-1");
1834 Assert.AreEqual (2, b, "c-2");
1838 var d = t.ContinueWith ((a, b) => {
1839 Assert.AreEqual (t, a, "d-1");
1840 Assert.AreEqual (3, b, "d-2");
1844 Assert.IsTrue (d.Wait (1000), "#1");
1846 Assert.AreEqual (1, t.AsyncState, "#2");
1847 Assert.AreEqual (80, t.Result, "#2r");
1848 Assert.AreEqual (2, c.AsyncState, "#3");
1849 Assert.AreEqual ("c", c.Result, "#3r");
1850 Assert.AreEqual (3, d.AsyncState, "#4");
1851 Assert.AreEqual ('d', d.Result, "#3r");
1855 public void ContinueWith_CustomScheduleRejected ()
1857 var scheduler = new NonInlineableScheduler ();
1858 var t = Task.Factory.StartNew (delegate { }).
1859 ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
1861 Assert.IsTrue (t.Wait (5000));
1865 public void FromResult ()
1867 var t = Task.FromResult<object> (null);
1868 Assert.IsTrue (t.IsCompleted, "#1");
1869 Assert.AreEqual (null, t.Result, "#2");
1875 public void LongRunning ()
1879 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1881 Assert.IsTrue (t.Wait (5000), "#0");
1882 Assert.IsTrue ((bool)is_tp, "#1");
1883 Assert.IsTrue ((bool)is_bg, "#2");
1887 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1889 Assert.IsTrue (t.Wait (5000), "#10");
1890 Assert.IsFalse ((bool) is_tp, "#11");
1891 Assert.IsTrue ((bool) is_bg, "#12");
1895 public void Run_ArgumentCheck ()
1898 Task.Run (null as Action);
1900 } catch (ArgumentNullException) {
1907 bool ranOnDefaultScheduler = false;
1908 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1909 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1911 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1915 public void Run_Cancel ()
1917 var t = Task.Run (() => 1, new CancellationToken (true));
1921 } catch (AggregateException) {
1924 Assert.IsTrue (t.IsCanceled, "#2");
1928 public void Run_ExistingTaskT ()
1930 var t = new Task<int> (() => 5);
1931 var t2 = Task.Run (() => { t.Start (); return t; });
1933 Assert.IsTrue (t2.Wait (1000), "#1");
1934 Assert.AreEqual (5, t2.Result, "#2");
1938 public void Run_ExistingTask ()
1940 var t = new Task (delegate { throw new Exception ("Foo"); });
1941 var t2 = Task.Run (() => { t.Start (); return t; });
1946 } catch (Exception) {}
1948 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1952 public void DenyChildAttachTest ()
1954 var mre = new ManualResetEventSlim ();
1956 Task parent = Task.Factory.StartNew (() => {
1957 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1958 }, TaskCreationOptions.DenyChildAttach);
1959 Assert.IsTrue (parent.Wait (1000), "#1");
1961 Assert.IsTrue (nested.Wait (2000), "#2");
1964 class SynchronousScheduler : TaskScheduler
1966 protected override IEnumerable<Task> GetScheduledTasks ()
1968 throw new NotImplementedException ();
1971 protected override void QueueTask (Task task)
1973 TryExecuteTaskInline (task, false);
1976 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1978 return base.TryExecuteTask (task);
1983 public void HideSchedulerTest ()
1985 var mre = new ManualResetEventSlim ();
1986 var ranOnDefault = false;
1987 var scheduler = new SynchronousScheduler ();
1989 Task parent = Task.Factory.StartNew (() => {
1990 Task.Factory.StartNew (() => {
1991 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1994 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
1996 Assert.IsTrue (mre.Wait (1000), "#1");
1997 Assert.IsTrue (ranOnDefault, "#2");
2001 public void LazyCancelationTest ()
2003 var source = new CancellationTokenSource ();
2005 var parent = new Task (delegate {});
2006 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
2008 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
2011 Assert.IsTrue (cont.Wait (1000), "#2");
2013 } catch (AggregateException ex) {
2014 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
2019 public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
2022 var child = Task.Factory.StartNew (() => {
2023 inner = Task.Run (() => {
2024 throw new ApplicationException ();
2025 }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
2029 var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
2030 Assert.IsTrue (t.Wait (5000), "#1");
2031 Assert.AreEqual (1, counter, "#2");
2032 Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
2033 Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
2037 [Category("NotWorking")]
2038 public void TaskContinuationChainLeak()
2040 // Start cranking out tasks, starting each new task upon completion of and from inside the prior task.
2042 var tester = new TaskContinuationChainLeakTester ();
2044 tester.TasksPilledUp.WaitOne ();
2046 // Head task should be out of scope by now. Manually run the GC and expect that it gets collected.
2049 GC.WaitForPendingFinalizers ();
2052 // It's important that we do the asserting while the task recursion is still going, since that is the
2053 // crux of the problem scenario.
2061 class TaskContinuationChainLeakTester
2063 volatile bool m_bStop;
2065 ManualResetEvent mre = new ManualResetEvent (false);
2066 WeakReference<Task> headTaskWeakRef;
2068 public ManualResetEvent TasksPilledUp {
2076 headTaskWeakRef = new WeakReference<Task> (StartNewTask ());
2079 public Task StartNewTask ()
2084 if (++counter == 50)
2087 return Task.Factory.StartNew (DummyWorker).ContinueWith (task => StartNewTask ());
2095 public void Verify ()
2098 Assert.IsFalse (headTaskWeakRef.TryGetTarget (out task));