}
}
+ int workerThreads;
+ int completionPortThreads;
Task[] tasks;
const int max = 6;
+ object cleanup_mutex = new object ();
+ List<Task> cleanup_list;
[SetUp]
public void Setup()
{
- tasks = new Task[max];
+ ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
+ ThreadPool.SetMinThreads (1, 1);
+
+ tasks = new Task[max];
+ cleanup_list = new List<Task> ();
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ ThreadPool.SetMinThreads (workerThreads, completionPortThreads);
+ Task[] l = null;
+ lock (cleanup_mutex) {
+ l = cleanup_list.ToArray ();
+ }
+ try {
+ Task.WaitAll (l);
+ } catch (Exception) {
+ }
+ }
+
+ void AddToCleanup (Task[] tasks) {
+ lock (cleanup_mutex) {
+ foreach (var t in tasks)
+ cleanup_list.Add (t);
+ }
+ }
+
+ void AddToCleanup (Task task) {
+ lock (cleanup_mutex) {
+ cleanup_list.Add (task);
+ }
}
void InitWithDelegate(Action action)
for (int i = 0; i < max; i++) {
tasks[i] = Task.Factory.StartNew(action);
}
+ AddToCleanup (tasks);
}
[Test]
{
var mre = new ManualResetEventSlim (false);
var tasks = new Task[] {
- Task.Factory.StartNew (delegate { mre.Wait (1000); }),
+ Task.Factory.StartNew (delegate { mre.Wait (5000); }),
Task.Factory.StartNew (delegate { throw new ApplicationException (); })
};
- Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
+ Assert.AreEqual (1, Task.WaitAny (tasks, 3000), "#1");
Assert.IsFalse (tasks[0].IsCompleted, "#2");
Assert.IsTrue (tasks[1].IsFaulted, "#3");
for (int i = 0; i < tasks.Length; i++) {
tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
}
+ AddToCleanup (tasks);
Assert.IsTrue (Task.WaitAll (tasks, 5000));
}
CountdownEvent cde = new CountdownEvent (2);
var mre = new ManualResetEvent (false);
var tasks = new[] {
- Task.Factory.StartNew (delegate { mre.WaitOne (); }),
+ Task.Factory.StartNew (delegate { Assert.IsTrue (mre.WaitOne (1500), "#0"); }),
Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
};
mre.Set ();
try {
- Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
+ Task.WaitAll (tasks, 1000);
Assert.Fail ("#4");
} catch (AggregateException e) {
Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
Assert.AreEqual (true, previouslyQueued);
}
- [Test, ExpectedException (typeof (InvalidOperationException))]
+ [Test]
public void CreationWhileInitiallyCanceled ()
{
var token = new CancellationToken (true);
var task = new Task (() => { }, token);
- Assert.AreEqual (TaskStatus.Canceled, task.Status);
- task.Start ();
+
+ try {
+ task.Start ();
+ Assert.Fail ("#1");
+ } catch (InvalidOperationException) {
+ }
+
+ try {
+ task.Wait ();
+ Assert.Fail ("#2");
+ } catch (AggregateException e) {
+ Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
+ }
+
+ Assert.IsTrue (task.IsCanceled, "#4");
}
[Test]
try {
task.ContinueWith (null);
Assert.Fail ("#1");
- } catch (ArgumentException) {
+ } catch (ArgumentNullException e) {
}
try {
task.ContinueWith (delegate { }, null);
Assert.Fail ("#2");
- } catch (ArgumentException) {
+ } catch (ArgumentNullException e) {
}
try {
task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
Assert.Fail ("#3");
- } catch (ArgumentException) {
+ } catch (ArgumentOutOfRangeException) {
}
try {
task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
Assert.Fail ("#4");
- } catch (ArgumentException) {
+ } catch (ArgumentOutOfRangeException) {
}
}
public void ContinueWithChildren ()
{
ParallelTestHelper.Repeat (delegate {
- bool result = false;
+ bool result = false;
- var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
+ var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
var mre = new ManualResetEvent (false);
- t.ContinueWith (l => {
+ t.ContinueWith (l => {
result = true;
mre.Set ();
});
Assert.IsTrue (mre.WaitOne (1000), "#1");
- Assert.IsTrue (result, "#2");
+ Assert.IsTrue (result, "#2");
}, 2);
}
{
ParallelTestHelper.Repeat (delegate {
var evt = new ManualResetEventSlim ();
- var t = Task.Factory.StartNew (() => evt.Wait (5000));
+ var monitor = new object ();
+ int finished = 0;
+ var t = Task.Factory.StartNew (delegate {
+ var r = evt.Wait (5000);
+ lock (monitor) {
+ finished ++;
+ Monitor.Pulse (monitor);
+ }
+ return r ? 1 : 10; //1 -> ok, 10 -> evt wait failed
+ });
var cntd = new CountdownEvent (2);
var cntd2 = new CountdownEvent (2);
- bool r1 = false, r2 = false;
- ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); });
- ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); });
-
+ int r1 = 0, r2 = 0;
+ ThreadPool.QueueUserWorkItem (delegate {
+ cntd.Signal ();
+ if (!t.Wait (1000))
+ r1 = 20; // 20 -> task wait failed
+ else if (t.Result != 1)
+ r1 = 30 + t.Result; // 30 -> task result is bad
+ else
+ r1 = 2; //2 -> ok
+ cntd2.Signal ();
+ lock (monitor) {
+ finished ++;
+ Monitor.Pulse (monitor);
+ }
+ });
+ ThreadPool.QueueUserWorkItem (delegate {
+ cntd.Signal ();
+ if (!t.Wait (1000))
+ r2 = 40; // 40 -> task wait failed
+ else if (t.Result != 1)
+ r2 = 50 + t.Result; // 50 -> task result is bad
+ else
+ r2 = 3; //3 -> ok
+
+ cntd2.Signal ();
+ lock (monitor) {
+ finished ++;
+ Monitor.Pulse (monitor);
+ }
+ });
Assert.IsTrue (cntd.Wait (2000), "#1");
evt.Set ();
Assert.IsTrue (cntd2.Wait (2000), "#2");
- Assert.IsTrue (r1, "r1");
- Assert.IsTrue (r2, "r2");
+ Assert.AreEqual (2, r1, "r1");
+ Assert.AreEqual (3, r2, "r2");
+
+ // Wait for everything to finish to avoid overloading the tpool
+ lock (monitor) {
+ while (true) {
+ if (finished == 3)
+ break;
+ else
+ Monitor.Wait (monitor);
+ }
+ }
}, 10);
}
};
var inner = new ApplicationException ();
Thread t = new Thread (delegate () {
- Task.Factory.StartNew (() => { Console.WriteLine ("HIT!"); throw inner; });
+ Task.Factory.StartNew (() => { throw inner; });
});
t.Start ();
t.Join ();
[Test]
public void Start_NullArgument ()
{
- var t = Task.Factory.StartNew (delegate () { });
+ var t = new Task (() => { });
try {
t.Start (null);
Assert.Fail ();
});
var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
testTask.RunSynchronously ();
- onErrorTask.Wait (100);
+ onErrorTask.Wait (1000);
Assert.IsNotNull (e);
Assert.IsTrue (continuationRan);
}
var t = new Task (() => {
new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
- });
+ });
t.RunSynchronously ();
Assert.IsTrue (r1);
bool? is_bg = null;
var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
t.Start ();
- Assert.IsTrue (t.Wait (100));
+ Assert.IsTrue (t.Wait (5000), "#0");
Assert.IsTrue ((bool)is_tp, "#1");
Assert.IsTrue ((bool)is_bg, "#2");
is_bg = null;
t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
t.Start ();
-
- Assert.IsTrue (t.Wait (100));
+ Assert.IsTrue (t.Wait (5000), "#10");
Assert.IsFalse ((bool) is_tp, "#11");
Assert.IsTrue ((bool) is_bg, "#12");
}
}
}
+ [Test]
+ public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
+ {
+ Task inner = null;
+ var child = Task.Factory.StartNew (() => {
+ inner = Task.Run (() => {
+ throw new ApplicationException ();
+ }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
+ });
+
+ int counter = 0;
+ var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
+ Assert.IsTrue (t.Wait (5000), "#1");
+ Assert.AreEqual (1, counter, "#2");
+ Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
+ Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
+ }
+
[Test]
[Category("NotWorking")]
public void TaskContinuationChainLeak()