5 // Marek Safar <marek.safar@gmail.com>
7 // Copyright (c) 2008 Jérémie "Garuma" Laval
8 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33 using System.Threading;
34 using System.Threading.Tasks;
35 using System.Collections.Generic;
36 using NUnit.Framework;
39 using NUnit.Framework.SyntaxHelpers;
42 namespace MonoTests.System.Threading.Tasks
45 public class TaskTests
47 class MockScheduler : TaskScheduler
49 public event Action<Task, bool> TryExecuteTaskInlineHandler;
51 protected override IEnumerable<Task> GetScheduledTasks ()
53 throw new NotImplementedException ();
56 protected override void QueueTask (Task task)
61 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
63 if (TryExecuteTaskInlineHandler != null)
64 TryExecuteTaskInlineHandler (task, taskWasPreviouslyQueued);
66 return base.TryExecuteTask (task);
70 class NonInlineableScheduler : TaskScheduler
72 protected override IEnumerable<Task> GetScheduledTasks ()
74 throw new NotImplementedException ();
77 protected override void QueueTask (Task task)
79 if (!base.TryExecuteTask (task))
80 throw new ApplicationException ();
83 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
89 class ExceptionScheduler : TaskScheduler
91 protected override IEnumerable<Task> GetScheduledTasks ()
93 throw new ApplicationException ("1");
96 protected override void QueueTask (Task task)
98 throw new ApplicationException ("2");
101 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
103 throw new ApplicationException ("3");
108 int completionPortThreads;
112 object cleanup_mutex = new object ();
113 List<Task> cleanup_list;
118 ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
119 ThreadPool.SetMinThreads (1, 1);
121 tasks = new Task[max];
122 cleanup_list = new List<Task> ();
126 public void Teardown()
128 ThreadPool.SetMinThreads (workerThreads, completionPortThreads);
130 lock (cleanup_mutex) {
131 l = cleanup_list.ToArray ();
135 } catch (Exception) {
139 void AddToCleanup (Task[] tasks) {
140 lock (cleanup_mutex) {
141 foreach (var t in tasks)
142 cleanup_list.Add (t);
146 void AddToCleanup (Task task) {
147 lock (cleanup_mutex) {
148 cleanup_list.Add (task);
152 void InitWithDelegate(Action action)
154 for (int i = 0; i < max; i++) {
155 tasks[i] = Task.Factory.StartNew(action);
157 AddToCleanup (tasks);
161 public void WaitAnyTest()
163 ParallelTestHelper.Repeat (delegate {
167 InitWithDelegate(delegate {
168 int times = Interlocked.Exchange (ref flag, 1);
170 SpinWait sw = new SpinWait ();
171 while (finished == 0) sw.SpinOnce ();
173 Interlocked.Increment (ref finished);
177 int index = Task.WaitAny(tasks, 1000);
179 Assert.AreNotEqual (-1, index, "#3");
180 Assert.AreEqual (1, flag, "#1");
181 Assert.AreEqual (1, finished, "#2");
186 public void WaitAny_Empty ()
188 Assert.AreEqual (-1, Task.WaitAny (new Task[0]));
192 public void WaitAny_Zero ()
194 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { })}, 0), "#1");
195 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { }) }, 20), "#1");
199 public void WaitAny_Cancelled ()
201 var cancelation = new CancellationTokenSource ();
202 var tasks = new Task[] {
203 new Task (delegate { }),
204 new Task (delegate { }, cancelation.Token)
207 cancelation.Cancel ();
209 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
210 Assert.IsTrue (tasks[1].IsCompleted, "#2");
211 Assert.IsTrue (tasks[1].IsCanceled, "#3");
215 public void WaitAny_CancelledWithoutExecution ()
217 var cancelation = new CancellationTokenSource ();
218 var tasks = new Task[] {
219 new Task (delegate { }),
220 new Task (delegate { })
224 var mre = new ManualResetEventSlim (false);
225 ThreadPool.QueueUserWorkItem (delegate {
226 res = Task.WaitAny (tasks, 20);
230 cancelation.Cancel ();
231 Assert.IsTrue (mre.Wait (1000), "#1");
232 Assert.AreEqual (-1, res);
236 public void WaitAny_OneException ()
238 var mre = new ManualResetEventSlim (false);
239 var tasks = new Task[] {
240 Task.Factory.StartNew (delegate { mre.Wait (5000); }),
241 Task.Factory.StartNew (delegate { throw new ApplicationException (); })
244 Assert.AreEqual (1, Task.WaitAny (tasks, 3000), "#1");
245 Assert.IsFalse (tasks[0].IsCompleted, "#2");
246 Assert.IsTrue (tasks[1].IsFaulted, "#3");
252 public void WaitAny_SingleCanceled ()
254 var src = new CancellationTokenSource ();
255 var t = Task.Factory.StartNew (() => { Thread.Sleep (200); src.Cancel (); src.Token.ThrowIfCancellationRequested (); }, src.Token);
256 Assert.AreEqual (0, Task.WaitAny (new [] { t }));
259 public void WaitAny_ManyExceptions ()
261 CountdownEvent cde = new CountdownEvent (3);
263 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
264 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
265 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
268 Assert.IsTrue (cde.Wait (1000), "#1");
271 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#2");
272 } catch (AggregateException e) {
273 Assert.AreEqual (3, e.InnerExceptions.Count, "#3");
278 public void WaitAny_ManyCanceled ()
280 var cancellation = new CancellationToken (true);
282 Task.Factory.StartNew (delegate { }, cancellation),
283 Task.Factory.StartNew (delegate { }, cancellation),
284 Task.Factory.StartNew (delegate { }, cancellation)
288 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#1");
289 } catch (AggregateException e) {
290 Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
295 public void WaitAllTest ()
297 ParallelTestHelper.Repeat (delegate {
299 InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
301 Assert.AreEqual(max, achieved, "#1");
306 public void WaitAll_ManyTasks ()
308 for (int r = 0; r < 2000; ++r) {
309 var tasks = new Task[60];
311 for (int i = 0; i < tasks.Length; i++) {
312 tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
314 AddToCleanup (tasks);
316 Assert.IsTrue (Task.WaitAll (tasks, 5000));
321 public void WaitAll_Zero ()
323 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 0), "#0");
324 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 10), "#1");
328 public void WaitAll_WithExceptions ()
330 InitWithDelegate (delegate { throw new ApplicationException (); });
333 Task.WaitAll (tasks);
335 } catch (AggregateException e) {
336 Assert.AreEqual (6, e.InnerExceptions.Count, "#2");
339 Assert.IsNotNull (tasks[0].Exception, "#3");
343 public void WaitAll_TimeoutWithExceptionsAfter ()
345 CountdownEvent cde = new CountdownEvent (2);
346 var mre = new ManualResetEvent (false);
348 Task.Factory.StartNew (delegate { Assert.IsTrue (mre.WaitOne (1500), "#0"); }),
349 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
350 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
353 Assert.IsTrue (cde.Wait (1000), "#1");
354 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
359 Task.WaitAll (tasks, 1000);
361 } catch (AggregateException e) {
362 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
367 public void WaitAll_TimeoutWithExceptionsBefore ()
369 CountdownEvent cde = new CountdownEvent (2);
370 var mre = new ManualResetEvent (false);
372 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
373 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
374 Task.Factory.StartNew (delegate { mre.WaitOne (); })
377 Assert.IsTrue (cde.Wait (1000), "#1");
378 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
383 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
385 } catch (AggregateException e) {
386 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
391 public void WaitAll_Cancelled ()
393 var cancelation = new CancellationTokenSource ();
394 var tasks = new Task[] {
395 new Task (delegate { cancelation.Cancel (); }),
396 new Task (delegate { }, cancelation.Token)
402 Task.WaitAll (tasks);
404 } catch (AggregateException e) {
405 var inner = (TaskCanceledException) e.InnerException;
406 Assert.AreEqual (tasks[1], inner.Task, "#2");
409 Assert.IsTrue (tasks[0].IsCompleted, "#3");
410 Assert.IsTrue (tasks[1].IsCanceled, "#4");
415 public void WaitAll_CancelledAndTimeout ()
417 var ct = new CancellationToken (true);
418 var t1 = new Task (() => {}, ct);
419 var t2 = Task.Delay (3000);
420 Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
425 public void WaitAllExceptionThenCancelled ()
427 var cancelation = new CancellationTokenSource ();
428 var tasks = new Task[] {
429 new Task (delegate { cancelation.Cancel (); throw new ApplicationException (); }),
430 new Task (delegate { }, cancelation.Token)
436 Task.WaitAll (tasks);
438 } catch (AggregateException e) {
439 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#2");
440 var inner = (TaskCanceledException) e.InnerExceptions[1];
441 Assert.AreEqual (tasks[1], inner.Task, "#3");
444 Assert.IsTrue (tasks[0].IsCompleted, "#4");
445 Assert.IsTrue (tasks[1].IsCanceled, "#5");
449 public void WaitAll_StartedUnderWait ()
451 var task1 = new Task (delegate { });
453 ThreadPool.QueueUserWorkItem (delegate {
454 // Sleep little to let task to start and hit internal wait
459 Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
463 public void CancelBeforeStart ()
465 var src = new CancellationTokenSource ();
467 Task t = new Task (delegate { }, src.Token);
469 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
474 } catch (InvalidOperationException) {
479 public void Wait_CancelledTask ()
481 var src = new CancellationTokenSource ();
483 Task t = new Task (delegate { }, src.Token);
489 } catch (AggregateException e) {
490 var details = (TaskCanceledException) e.InnerException;
491 Assert.AreEqual (t, details.Task, "#1e");
497 } catch (AggregateException e) {
498 var details = (TaskCanceledException) e.InnerException;
499 Assert.AreEqual (t, details.Task, "#2e");
500 Assert.IsNull (details.Task.Exception, "#2e2");
505 public void Wait_Inlined ()
507 bool? previouslyQueued = null;
509 var scheduler = new MockScheduler ();
510 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
511 previouslyQueued = b;
514 var tf = new TaskFactory (scheduler);
515 var t = tf.StartNew (() => { });
518 Assert.AreEqual (true, previouslyQueued);
522 public void CreationWhileInitiallyCanceled ()
524 var token = new CancellationToken (true);
525 var task = new Task (() => { }, token);
530 } catch (InvalidOperationException) {
536 } catch (AggregateException e) {
537 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
540 Assert.IsTrue (task.IsCanceled, "#4");
544 public void ContinueWithInvalidArguments ()
546 var task = new Task (() => { });
548 task.ContinueWith (null);
550 } catch (ArgumentNullException e) {
554 task.ContinueWith (delegate { }, null);
556 } catch (ArgumentNullException e) {
560 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
562 } catch (ArgumentOutOfRangeException) {
566 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
568 } catch (ArgumentOutOfRangeException) {
573 public void ContinueWithOnAnyTestCase()
575 ParallelTestHelper.Repeat (delegate {
578 Task t = Task.Factory.StartNew(delegate { });
579 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
580 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
581 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
582 Assert.IsNull(cont.Exception, "#1");
583 Assert.IsNotNull(cont, "#2");
584 Assert.IsTrue(result, "#3");
589 public void ContinueWithOnCompletedSuccessfullyTestCase()
591 ParallelTestHelper.Repeat (delegate {
594 Task t = Task.Factory.StartNew(delegate { });
595 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
596 Assert.IsTrue (t.Wait(1000), "#4");
597 Assert.IsTrue (cont.Wait(1000), "#5");
599 Assert.IsNull(cont.Exception, "#1");
600 Assert.IsNotNull(cont, "#2");
601 Assert.IsTrue(result, "#3");
606 public void ContinueWithOnAbortedTestCase()
609 bool taskResult = false;
611 CancellationTokenSource src = new CancellationTokenSource ();
612 Task t = new Task (delegate { taskResult = true; }, src.Token);
614 Task cont = t.ContinueWith (delegate { result = true; },
615 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
619 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
620 Assert.IsTrue (cont.IsCompleted, "#1b");
621 Assert.IsTrue (result, "#1c");
626 } catch (InvalidOperationException) {
629 Assert.IsTrue (cont.Wait (1000), "#3");
631 Assert.IsFalse (taskResult, "#4");
633 Assert.IsNull (cont.Exception, "#5");
634 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
638 public void ContinueWithOnFailedTestCase()
640 ParallelTestHelper.Repeat (delegate {
643 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
644 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
646 Assert.IsTrue (cont.Wait(1000), "#0");
647 Assert.IsNotNull (t.Exception, "#1");
648 Assert.IsNotNull (cont, "#2");
649 Assert.IsTrue (result, "#3");
654 public void ContinueWithWithStart ()
656 Task t = new Task<int> (() => 1);
657 t = t.ContinueWith (l => { });
661 } catch (InvalidOperationException) {
666 public void ContinueWithChildren ()
668 ParallelTestHelper.Repeat (delegate {
671 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
673 var mre = new ManualResetEvent (false);
674 t.ContinueWith (l => {
679 Assert.IsTrue (mre.WaitOne (1000), "#1");
680 Assert.IsTrue (result, "#2");
685 public void ContinueWithDifferentOptionsAreCanceledTest ()
687 var mre = new ManualResetEventSlim ();
688 var task = Task.Factory.StartNew (() => mre.Wait (200));
689 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
690 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
691 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
694 contSuccess.Wait (100);
696 Assert.IsTrue (contSuccess.IsCompleted);
697 Assert.IsTrue (contFailed.IsCompleted);
698 Assert.IsTrue (contCanceled.IsCompleted);
699 Assert.IsFalse (contSuccess.IsCanceled);
700 Assert.IsTrue (contFailed.IsCanceled);
701 Assert.IsTrue (contCanceled.IsCanceled);
705 public void MultipleTasks()
707 ParallelTestHelper.Repeat (delegate {
708 bool r1 = false, r2 = false, r3 = false;
710 Task t1 = Task.Factory.StartNew(delegate {
713 Task t2 = Task.Factory.StartNew(delegate {
716 Task t3 = Task.Factory.StartNew(delegate {
724 Assert.IsTrue(r1, "#1");
725 Assert.IsTrue(r2, "#2");
726 Assert.IsTrue(r3, "#3");
731 public void WaitChildTestCase()
733 ParallelTestHelper.Repeat (delegate {
734 bool r1 = false, r2 = false, r3 = false;
735 var mre = new ManualResetEventSlim (false);
736 var mreStart = new ManualResetEventSlim (false);
738 Task t = Task.Factory.StartNew(delegate {
739 Task.Factory.StartNew(delegate {
742 }, TaskCreationOptions.AttachedToParent);
743 Task.Factory.StartNew(delegate {
745 }, TaskCreationOptions.AttachedToParent);
746 Task.Factory.StartNew(delegate {
748 }, TaskCreationOptions.AttachedToParent);
753 Assert.IsFalse (t.Wait (10), "#0a");
755 Assert.IsTrue (t.Wait (500), "#0b");
756 Assert.IsTrue(r2, "#1");
757 Assert.IsTrue(r3, "#2");
758 Assert.IsTrue(r1, "#3");
759 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
766 public void WaitingForChildrenToComplete ()
769 var mre = new ManualResetEvent (false);
771 parent_wfc = Task.Factory.StartNew (() => {
772 nested = Task.Factory.StartNew (() => {
773 Assert.IsTrue (mre.WaitOne (4000), "parent_wfc needs to be set first");
774 Assert.IsFalse (parent_wfc.Wait (10), "#1a");
775 Assert.AreEqual (TaskStatus.WaitingForChildrenToComplete, parent_wfc.Status, "#1b");
776 }, TaskCreationOptions.AttachedToParent).ContinueWith (l => {
777 Assert.IsTrue (parent_wfc.Wait (2000), "#2a");
778 Assert.AreEqual (TaskStatus.RanToCompletion, parent_wfc.Status, "#2b");
779 }, TaskContinuationOptions.ExecuteSynchronously);
783 Assert.IsTrue (parent_wfc.Wait (2000), "#3");
784 Assert.IsTrue (nested.Wait (2000), "#4");
788 public void WaitChildWithContinuationAttachedTest ()
791 var task = new Task(() =>
793 Task.Factory.StartNew(() => {
795 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
798 }, TaskContinuationOptions.AttachedToParent);
802 Assert.IsTrue (result);
806 public void WaitChildWithContinuationNotAttachedTest ()
808 var task = new Task(() =>
810 Task.Factory.StartNew(() => {
812 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
817 Assert.IsTrue (task.Wait(400));
821 public void WaitChildWithNesting ()
824 var t = Task.Factory.StartNew (() => {
825 Task.Factory.StartNew (() => {
826 Task.Factory.StartNew (() => {
829 }, TaskCreationOptions.AttachedToParent);
830 }, TaskCreationOptions.AttachedToParent);
832 Assert.IsTrue (t.Wait (4000), "#1");
833 Assert.IsTrue (result, "#2");
837 public void DoubleWaitTest ()
839 ParallelTestHelper.Repeat (delegate {
840 var evt = new ManualResetEventSlim ();
841 var monitor = new object ();
843 var t = Task.Factory.StartNew (delegate {
844 var r = evt.Wait (5000);
847 Monitor.Pulse (monitor);
849 return r ? 1 : 10; //1 -> ok, 10 -> evt wait failed
851 var cntd = new CountdownEvent (2);
852 var cntd2 = new CountdownEvent (2);
855 ThreadPool.QueueUserWorkItem (delegate {
858 r1 = 20; // 20 -> task wait failed
859 else if (t.Result != 1)
860 r1 = 30 + t.Result; // 30 -> task result is bad
866 Monitor.Pulse (monitor);
869 ThreadPool.QueueUserWorkItem (delegate {
872 r2 = 40; // 40 -> task wait failed
873 else if (t.Result != 1)
874 r2 = 50 + t.Result; // 50 -> task result is bad
881 Monitor.Pulse (monitor);
884 Assert.IsTrue (cntd.Wait (2000), "#1");
886 Assert.IsTrue (cntd2.Wait (2000), "#2");
887 Assert.AreEqual (2, r1, "r1");
888 Assert.AreEqual (3, r2, "r2");
890 // Wait for everything to finish to avoid overloading the tpool
896 Monitor.Wait (monitor);
903 public void DoubleTimeoutedWaitTest ()
905 var evt = new ManualResetEventSlim ();
906 var t = new Task (delegate { });
907 var cntd = new CountdownEvent (2);
909 bool r1 = false, r2 = false;
910 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
911 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
919 public void RunSynchronously ()
922 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
923 t.RunSynchronously ();
925 Assert.AreEqual (1, val, "#1");
927 t = new Task (() => { Thread.Sleep (0); val = 2; });
929 bool? previouslyQueued = null;
931 var scheduler = new MockScheduler ();
932 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
933 previouslyQueued = b;
936 t.RunSynchronously (scheduler);
938 Assert.AreEqual (2, val, "#2");
939 Assert.AreEqual (false, previouslyQueued, "#2a");
943 public void RunSynchronouslyArgumentChecks ()
945 Task t = new Task (() => { });
947 t.RunSynchronously (null);
949 } catch (ArgumentNullException) {
954 public void RunSynchronously_SchedulerException ()
956 var scheduler = new MockScheduler ();
957 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
958 throw new ApplicationException ();
961 Task t = new Task (() => { });
963 t.RunSynchronously (scheduler);
965 } catch (Exception e) {
966 Assert.AreEqual (t.Exception.InnerException, e);
971 public void RunSynchronouslyWithAttachedChildren ()
974 var t = new Task (() => {
975 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
977 t.RunSynchronously ();
978 Assert.IsTrue (result);
982 public void RunSynchronouslyOnContinuation ()
984 Task t = new Task<int> (() => 1);
985 t = t.ContinueWith (l => { });
987 t.RunSynchronously ();
989 } catch (InvalidOperationException) {
994 public void UnobservedExceptionOnFinalizerThreadTest ()
996 bool wasCalled = false;
997 TaskScheduler.UnobservedTaskException += (o, args) => {
1001 var inner = new ApplicationException ();
1002 Thread t = new Thread (delegate () {
1003 Task.Factory.StartNew (() => { throw inner; });
1007 Thread.Sleep (1000);
1009 Thread.Sleep (1000);
1010 GC.WaitForPendingFinalizers ();
1012 Assert.IsTrue (wasCalled);
1015 [Test, ExpectedException (typeof (InvalidOperationException))]
1016 public void StartFinishedTaskTest ()
1018 var t = Task.Factory.StartNew (delegate () { });
1025 public void Start_NullArgument ()
1027 var t = new Task (() => { });
1031 } catch (ArgumentNullException) {
1035 [Test, ExpectedException (typeof (InvalidOperationException))]
1036 public void DisposeUnstartedTest ()
1038 var t = new Task (() => { });
1043 public void ThrowingUnrelatedCanceledExceptionTest ()
1045 Task t = new Task (() => {
1046 throw new TaskCanceledException ();
1049 t.RunSynchronously ();
1050 Assert.IsTrue (t.IsFaulted);
1051 Assert.IsFalse (t.IsCanceled);
1055 public void CanceledContinuationExecuteSynchronouslyTest ()
1057 var source = new CancellationTokenSource();
1058 var token = source.Token;
1059 var evt = new ManualResetEventSlim ();
1060 bool result = false;
1061 bool thrown = false;
1063 var task = Task.Factory.StartNew (() => evt.Wait (100));
1064 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
1071 } catch (Exception ex) {
1075 Assert.IsTrue (task.IsCompleted);
1076 Assert.IsTrue (cont.IsCanceled);
1077 Assert.IsFalse (result);
1078 Assert.IsTrue (thrown);
1082 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
1084 Task innerTask = null;
1085 var testTask = new Task (() =>
1087 innerTask = new Task (() =>
1089 throw new InvalidOperationException ();
1090 }, TaskCreationOptions.AttachedToParent);
1091 innerTask.RunSynchronously ();
1093 testTask.RunSynchronously ();
1095 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
1096 Assert.IsNotNull (innerTask);
1097 Assert.IsTrue (innerTask.IsFaulted);
1098 Assert.IsNotNull (testTask.Exception);
1099 Assert.IsTrue (testTask.IsFaulted);
1100 Assert.IsNotNull (innerTask.Exception);
1104 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
1106 var continuationRan = false;
1107 var testTask = new Task (() =>
1109 var task = new Task (() =>
1111 throw new InvalidOperationException();
1112 }, TaskCreationOptions.AttachedToParent);
1113 task.RunSynchronously ();
1115 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1116 testTask.RunSynchronously ();
1117 onErrorTask.Wait (100);
1118 Assert.IsTrue (continuationRan);
1122 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
1124 var continuationRan = false;
1125 var testTask = new Task (() =>
1127 var task = new Task (() =>
1129 throw new InvalidOperationException();
1130 }, TaskCreationOptions.AttachedToParent);
1131 task.RunSynchronously();
1133 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
1134 testTask.RunSynchronously ();
1135 Assert.IsTrue (onErrorTask.IsCompleted);
1136 Assert.IsFalse (onErrorTask.IsFaulted);
1137 Assert.IsFalse (continuationRan);
1141 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
1143 var continuationRan = false;
1144 AggregateException e = null;
1145 var testTask = new Task (() =>
1147 var child1 = new Task (() =>
1149 var child2 = new Task (() =>
1151 throw new InvalidOperationException();
1152 }, TaskCreationOptions.AttachedToParent);
1153 child2.RunSynchronously ();
1154 }, TaskCreationOptions.AttachedToParent);
1156 child1.RunSynchronously();
1157 e = child1.Exception;
1158 child1.Exception.Handle (ex => true);
1160 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1161 testTask.RunSynchronously ();
1162 onErrorTask.Wait (1000);
1163 Assert.IsNotNull (e);
1164 Assert.IsTrue (continuationRan);
1168 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1170 string result = "Failed";
1171 var testTask = new Task (() =>
1173 var child = new Task<string> (() =>
1176 }, TaskCreationOptions.AttachedToParent);
1177 child.RunSynchronously ();
1178 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1180 testTask.RunSynchronously ();
1182 Assert.AreEqual ("Success", result);
1186 public void InlineNotTrashingParentRelationship ()
1188 bool r1 = false, r2 = false;
1189 var t = new Task (() => {
1190 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1191 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1193 t.RunSynchronously ();
1200 public void AsyncWaitHandleSet ()
1202 var task = new TaskFactory ().StartNew (() => { });
1203 var ar = (IAsyncResult)task;
1204 Assert.IsFalse (ar.CompletedSynchronously, "#1");
1205 Assert.IsTrue (ar.AsyncWaitHandle.WaitOne (5000), "#2");
1209 public void StartOnBrokenScheduler ()
1211 var t = new Task (delegate { });
1214 t.Start (new ExceptionScheduler ());
1216 } catch (TaskSchedulerException e) {
1217 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1218 Assert.AreSame (e, t.Exception.InnerException, "#3");
1219 Assert.IsTrue (e.InnerException is ApplicationException, "#4");
1225 public void ContinuationOnBrokenScheduler ()
1227 var s = new ExceptionScheduler ();
1228 Task t = new Task(delegate {});
1230 var t2 = t.ContinueWith (delegate {
1231 }, TaskContinuationOptions.ExecuteSynchronously, s);
1233 var t3 = t.ContinueWith (delegate {
1234 }, TaskContinuationOptions.ExecuteSynchronously, s);
1239 Assert.IsTrue (t3.Wait (2000), "#0");
1241 } catch (AggregateException e) {
1244 Assert.AreEqual (TaskStatus.Faulted, t2.Status, "#2");
1245 Assert.AreEqual (TaskStatus.Faulted, t3.Status, "#3");
1249 public void Delay_Invalid ()
1253 } catch (ArgumentOutOfRangeException) {
1258 public void Delay_Start ()
1260 var t = Task.Delay (5000);
1263 } catch (InvalidOperationException) {
1268 public void Delay_Simple ()
1270 var t = Task.Delay (300);
1271 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1272 Assert.IsTrue (t.Wait (400), "#2");
1276 public void Delay_Cancelled ()
1278 var cancelation = new CancellationTokenSource ();
1280 var t = Task.Delay (5000, cancelation.Token);
1281 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1282 cancelation.Cancel ();
1286 } catch (AggregateException) {
1287 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1290 cancelation = new CancellationTokenSource ();
1291 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1292 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1293 cancelation.Cancel ();
1296 Assert.Fail ("#12");
1297 } catch (AggregateException) {
1298 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1303 public void Delay_TimeManagement ()
1305 var delay1 = Task.Delay(50);
1306 var delay2 = Task.Delay(25);
1307 Assert.IsTrue (Task.WhenAny(new[] { delay1, delay2 }).Wait (1000));
1308 Assert.AreEqual (TaskStatus.RanToCompletion, delay2.Status);
1312 public void WaitAny_WithNull ()
1314 var tasks = new [] {
1315 Task.FromResult (2),
1320 Task.WaitAny (tasks);
1322 } catch (ArgumentException) {
1327 public void WhenAll_Empty ()
1329 var tasks = new Task[0];
1331 Task t = Task.WhenAll(tasks);
1333 Assert.IsTrue(t.Wait(1000), "#1");
1337 public void WhenAll_WithNull ()
1340 Task.FromResult (2),
1345 Task.WhenAll (tasks);
1347 } catch (ArgumentException) {
1352 Task.WhenAll (tasks);
1354 } catch (ArgumentException) {
1359 public void WhenAll_Start ()
1361 Task[] tasks = new[] {
1362 Task.FromResult (2),
1365 var t = Task.WhenAll (tasks);
1366 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1371 } catch (InvalidOperationException) {
1375 new Task (delegate { }),
1378 t = Task.WhenAll (tasks);
1379 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1383 Assert.Fail ("#12");
1384 } catch (InvalidOperationException) {
1389 public void WhenAll_Cancelled ()
1391 var cancelation = new CancellationTokenSource ();
1392 var tasks = new Task[] {
1393 new Task (delegate { }),
1394 new Task (delegate { }, cancelation.Token)
1397 cancelation.Cancel ();
1399 var t = Task.WhenAll (tasks);
1400 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1404 Assert.IsTrue (t.Wait (1000), "#2");
1405 Assert.Fail ("#2a");
1406 } catch (AggregateException e) {
1407 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1412 public void WhenAll_Faulted ()
1414 var tcs = new TaskCompletionSource<object> ();
1415 tcs.SetException (new ApplicationException ());
1417 var tcs2 = new TaskCompletionSource<object> ();
1418 tcs2.SetException (new InvalidTimeZoneException ());
1420 var cancelation = new CancellationTokenSource ();
1421 var tasks = new Task[] {
1422 new Task (delegate { }),
1423 new Task (delegate { }, cancelation.Token),
1428 cancelation.Cancel ();
1430 var t = Task.WhenAll (tasks);
1431 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1435 Assert.IsTrue (t.Wait (1000), "#2");
1436 Assert.Fail ("#2a");
1437 } catch (AggregateException e) {
1438 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1439 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1444 public void WhenAll ()
1446 var t1 = new Task (delegate { });
1447 var t2 = new Task (delegate { t1.Start (); });
1449 var tasks = new Task[] {
1454 var t = Task.WhenAll (tasks);
1455 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1458 Assert.IsTrue (t.Wait (1000), "#2");
1462 public void WhenAllResult_Empty ()
1464 var tasks = new Task<int>[0];
1466 Task<int[]> t = Task.WhenAll(tasks);
1468 Assert.IsTrue(t.Wait(1000), "#1");
1469 Assert.IsNotNull(t.Result, "#2");
1470 Assert.AreEqual(t.Result.Length, 0, "#3");
1474 public void WhenAllResult_WithNull ()
1477 Task.FromResult (2),
1482 Task.WhenAll<int> (tasks);
1484 } catch (ArgumentException) {
1489 Task.WhenAll<int> (tasks);
1491 } catch (ArgumentException) {
1496 public void WhenAllResult_Cancelled ()
1498 var cancelation = new CancellationTokenSource ();
1499 var tasks = new [] {
1500 new Task<int> (delegate { return 9; }),
1501 new Task<int> (delegate { return 1; }, cancelation.Token)
1504 cancelation.Cancel ();
1506 var t = Task.WhenAll (tasks);
1507 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1511 Assert.IsTrue (t.Wait (1000), "#2");
1512 Assert.Fail ("#2a");
1513 } catch (AggregateException e) {
1514 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1520 } catch (AggregateException) {
1525 public void WhenAllResult ()
1527 var t1 = new Task<string> (delegate { return "a"; });
1528 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1530 var tasks = new [] {
1535 var t = Task.WhenAll<string> (tasks);
1536 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1539 Assert.IsTrue (t.Wait (1000), "#2");
1540 Assert.AreEqual (2, t.Result.Length, "#3");
1541 Assert.AreEqual ("a", t.Result[0], "#3a");
1542 Assert.AreEqual ("b", t.Result[1], "#3b");
1546 public void WhenAllResult_Completed ()
1549 Task.FromResult (1),
1553 var t = Task.WhenAll<int> (tasks);
1554 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1555 Assert.AreEqual (2, t.Result.Length, "#2");
1556 Assert.AreEqual (1, t.Result[0], "#2a");
1557 Assert.AreEqual (2, t.Result[1], "#2b");
1561 public void WhenAny_WithNull ()
1563 var tasks = new Task[] {
1564 Task.FromResult (2),
1569 Task.WhenAny (tasks);
1571 } catch (ArgumentException) {
1576 Task.WhenAny (tasks);
1578 } catch (ArgumentException) {
1582 Task.WhenAny (new Task[0]);
1584 } catch (ArgumentException) {
1589 public void WhenAny_Start ()
1591 Task[] tasks = new[] {
1592 Task.FromResult (2),
1595 var t = Task.WhenAny (tasks);
1596 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1601 } catch (InvalidOperationException) {
1605 new Task (delegate { }),
1608 t = Task.WhenAny (tasks);
1609 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1613 Assert.Fail ("#12");
1614 } catch (InvalidOperationException) {
1619 public void WhenAny_Cancelled ()
1621 var cancelation = new CancellationTokenSource ();
1622 var tasks = new Task[] {
1623 new Task (delegate { }),
1624 new Task (delegate { }, cancelation.Token)
1627 cancelation.Cancel ();
1629 var t = Task.WhenAny (tasks);
1630 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1633 Assert.IsTrue (t.Wait (1000), "#2");
1634 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1638 public void WhenAny_Faulted ()
1640 var tcs = new TaskCompletionSource<object> ();
1641 tcs.SetException (new ApplicationException ());
1643 var tcs2 = new TaskCompletionSource<object> ();
1644 tcs2.SetException (new InvalidTimeZoneException ());
1646 var cancelation = new CancellationTokenSource ();
1647 var tasks = new Task[] {
1648 new Task (delegate { }),
1650 new Task (delegate { }, cancelation.Token),
1654 cancelation.Cancel ();
1656 var t = Task.WhenAny (tasks);
1657 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1660 Assert.IsTrue (t.Wait (1000), "#2");
1661 Assert.IsNull (t.Exception, "#3");
1663 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1667 public void WhenAny ()
1669 var t1 = new Task (delegate { });
1670 var t2 = new Task (delegate { t1.Start (); });
1672 var tasks = new Task[] {
1677 var t = Task.WhenAny (tasks);
1678 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1681 Assert.IsTrue (t.Wait (1000), "#2");
1682 Assert.IsNotNull (t.Result, "#3");
1686 public void WhenAnyResult_WithNull ()
1688 var tasks = new [] {
1689 Task.FromResult (2),
1694 Task.WhenAny<int> (tasks);
1696 } catch (ArgumentException) {
1701 Task.WhenAny<int> (tasks);
1703 } catch (ArgumentException) {
1707 Task.WhenAny<short> (new Task<short>[0]);
1709 } catch (ArgumentException) {
1714 public void WhenAnyResult_Start ()
1717 Task.FromResult (2),
1720 var t = Task.WhenAny<int> (tasks);
1721 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1726 } catch (InvalidOperationException) {
1730 new Task<int> (delegate { return 55; }),
1733 t = Task.WhenAny<int> (tasks);
1734 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1738 Assert.Fail ("#12");
1739 } catch (InvalidOperationException) {
1744 public void WhenAnyResult_Cancelled ()
1746 var cancelation = new CancellationTokenSource ();
1747 var tasks = new [] {
1748 new Task<double> (delegate { return 1.1; }),
1749 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1752 cancelation.Cancel ();
1754 var t = Task.WhenAny<double> (tasks);
1755 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1758 Assert.IsTrue (t.Wait (1000), "#2");
1759 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1763 public void WhenAnyResult_Faulted ()
1765 var tcs = new TaskCompletionSource<object> ();
1766 tcs.SetException (new ApplicationException ());
1768 var tcs2 = new TaskCompletionSource<object> ();
1769 tcs2.SetException (new InvalidTimeZoneException ());
1771 var cancelation = new CancellationTokenSource ();
1772 var tasks = new Task<object>[] {
1773 new Task<object> (delegate { return null; }),
1775 new Task<object> (delegate { return ""; }, cancelation.Token),
1779 cancelation.Cancel ();
1781 var t = Task.WhenAny<object> (tasks);
1782 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1785 Assert.IsTrue (t.Wait (1000), "#2");
1786 Assert.IsNull (t.Exception, "#3");
1788 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1792 public void WhenAnyResult ()
1794 var t1 = new Task<byte> (delegate { return 3; });
1795 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1797 var tasks = new [] {
1802 var t = Task.WhenAny<byte> (tasks);
1803 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1806 Assert.IsTrue (t.Wait (1000), "#2");
1807 Assert.IsTrue (t.Result.Result > 1, "#3");
1811 public void ContinueWith_StateValue ()
1813 var t = Task.Factory.StartNew (l => {
1814 Assert.AreEqual (1, l, "a-1");
1817 var c = t.ContinueWith ((a, b) => {
1818 Assert.AreEqual (t, a, "c-1");
1819 Assert.AreEqual (2, b, "c-2");
1822 var d = t.ContinueWith ((a, b) => {
1823 Assert.AreEqual (t, a, "d-1");
1824 Assert.AreEqual (3, b, "d-2");
1828 Assert.IsTrue (d.Wait (1000), "#1");
1830 Assert.AreEqual (1, t.AsyncState, "#2");
1831 Assert.AreEqual (2, c.AsyncState, "#3");
1832 Assert.AreEqual (3, d.AsyncState, "#4");
1836 public void ContinueWith_StateValueGeneric ()
1838 var t = Task<int>.Factory.StartNew (l => {
1839 Assert.AreEqual (1, l, "a-1");
1843 var c = t.ContinueWith ((a, b) => {
1844 Assert.AreEqual (t, a, "c-1");
1845 Assert.AreEqual (2, b, "c-2");
1849 var d = t.ContinueWith ((a, b) => {
1850 Assert.AreEqual (t, a, "d-1");
1851 Assert.AreEqual (3, b, "d-2");
1855 Assert.IsTrue (d.Wait (1000), "#1");
1857 Assert.AreEqual (1, t.AsyncState, "#2");
1858 Assert.AreEqual (80, t.Result, "#2r");
1859 Assert.AreEqual (2, c.AsyncState, "#3");
1860 Assert.AreEqual ("c", c.Result, "#3r");
1861 Assert.AreEqual (3, d.AsyncState, "#4");
1862 Assert.AreEqual ('d', d.Result, "#3r");
1866 public void ContinueWith_CustomScheduleRejected ()
1868 var scheduler = new NonInlineableScheduler ();
1869 var t = Task.Factory.StartNew (delegate { }).
1870 ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
1872 Assert.IsTrue (t.Wait (5000));
1876 public void FromResult ()
1878 var t = Task.FromResult<object> (null);
1879 Assert.IsTrue (t.IsCompleted, "#1");
1880 Assert.AreEqual (null, t.Result, "#2");
1886 public void LongRunning ()
1890 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1892 Assert.IsTrue (t.Wait (5000), "#0");
1893 Assert.IsTrue ((bool)is_tp, "#1");
1894 Assert.IsTrue ((bool)is_bg, "#2");
1898 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1900 Assert.IsTrue (t.Wait (5000), "#10");
1901 Assert.IsFalse ((bool) is_tp, "#11");
1902 Assert.IsTrue ((bool) is_bg, "#12");
1906 public void Run_ArgumentCheck ()
1909 Task.Run (null as Action);
1911 } catch (ArgumentNullException) {
1918 bool ranOnDefaultScheduler = false;
1919 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1920 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1922 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1926 public void Run_Cancel ()
1928 var t = Task.Run (() => 1, new CancellationToken (true));
1932 } catch (AggregateException) {
1935 Assert.IsTrue (t.IsCanceled, "#2");
1939 public void Run_ExistingTaskT ()
1941 var t = new Task<int> (() => 5);
1942 var t2 = Task.Run (() => { t.Start (); return t; });
1944 Assert.IsTrue (t2.Wait (1000), "#1");
1945 Assert.AreEqual (5, t2.Result, "#2");
1949 public void Run_ExistingTask ()
1951 var t = new Task (delegate { throw new Exception ("Foo"); });
1952 var t2 = Task.Run (() => { t.Start (); return t; });
1957 } catch (Exception) {}
1959 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1963 public void DenyChildAttachTest ()
1965 var mre = new ManualResetEventSlim ();
1967 Task parent = Task.Factory.StartNew (() => {
1968 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1969 }, TaskCreationOptions.DenyChildAttach);
1970 Assert.IsTrue (parent.Wait (1000), "#1");
1972 Assert.IsTrue (nested.Wait (2000), "#2");
1975 class SynchronousScheduler : TaskScheduler
1977 protected override IEnumerable<Task> GetScheduledTasks ()
1979 throw new NotImplementedException ();
1982 protected override void QueueTask (Task task)
1984 TryExecuteTaskInline (task, false);
1987 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1989 return base.TryExecuteTask (task);
1994 public void HideSchedulerTest ()
1996 var mre = new ManualResetEventSlim ();
1997 var ranOnDefault = false;
1998 var scheduler = new SynchronousScheduler ();
2000 Task parent = Task.Factory.StartNew (() => {
2001 Task.Factory.StartNew (() => {
2002 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
2005 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
2007 Assert.IsTrue (mre.Wait (1000), "#1");
2008 Assert.IsTrue (ranOnDefault, "#2");
2012 public void LazyCancelationTest ()
2014 var source = new CancellationTokenSource ();
2016 var parent = new Task (delegate {});
2017 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
2019 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
2022 Assert.IsTrue (cont.Wait (1000), "#2");
2024 } catch (AggregateException ex) {
2025 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
2030 public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
2033 var child = Task.Factory.StartNew (() => {
2034 inner = Task.Run (() => {
2035 throw new ApplicationException ();
2036 }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
2040 var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
2041 Assert.IsTrue (t.Wait (5000), "#1");
2042 Assert.AreEqual (1, counter, "#2");
2043 Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
2044 Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
2048 [Category("NotWorking")]
2049 public void TaskContinuationChainLeak()
2051 // Start cranking out tasks, starting each new task upon completion of and from inside the prior task.
2053 var tester = new TaskContinuationChainLeakTester ();
2055 tester.TasksPilledUp.WaitOne ();
2057 // Head task should be out of scope by now. Manually run the GC and expect that it gets collected.
2060 GC.WaitForPendingFinalizers ();
2063 // It's important that we do the asserting while the task recursion is still going, since that is the
2064 // crux of the problem scenario.
2072 class TaskContinuationChainLeakTester
2074 volatile bool m_bStop;
2076 ManualResetEvent mre = new ManualResetEvent (false);
2077 WeakReference<Task> headTaskWeakRef;
2079 public ManualResetEvent TasksPilledUp {
2087 headTaskWeakRef = new WeakReference<Task> (StartNewTask ());
2090 public Task StartNewTask ()
2095 if (++counter == 50)
2098 return Task.Factory.StartNew (DummyWorker).ContinueWith (task => StartNewTask ());
2106 public void Verify ()
2109 Assert.IsFalse (headTaskWeakRef.TryGetTarget (out task));