Microsoft’s Task Parallel Library and the principle behind node.js

I wanted to see how Microsoft’s Task Parallel Library compared with node.js in so far as passing the next method in to the current to chain the calls indefinitely. So I created a method that iteratively adds itself to the current executing Task. The initial test was to see if the code would fail with a StackOverflowException but what I found instead was that I couldn’t get the Task to Wait unless I put the thread to sleep.

So this simple test fails, every time:

private volatile int count = 0;

[Test]
public void Wait_RecursiveAdditionalContinueWith_Waits()
{
    var start = new Task(() => { });
    start.ContinueWith(ContinuationMethod);

    start.Start();
    start.Wait();

    Assert.That(this.count, Is.EqualTo(100));
}

private void ContinuationMethod(Task task)
{
    count++;
    if (this.count < 100)
    {
        task.ContinueWith(ContinuationMethod);
    }
}

But if I swap start.Wait(); with Thread.Sleep(10); then it works fine. WFT? To cut a long story short … the ContinueWith method returns a child Task that you also need to wait for.

[Test]
public void Wait_RecursiveAdditionalContinueWith_Waits2()
{
    var start = new Task(() => { });
    var child = start.ContinueWith(ContinuationMethod2);

    start.Start();
    child.Wait();

    Assert.That(this.count, Is.EqualTo(100));
}

private void ContinuationMethod2(Task task)
{
    count++;
    if (this.count < 100)
    {
        var child = task.ContinueWith(ContinuationMethod2);
        child.Wait();
    }
}

Obvious once you know!

So, back to the initial question – how long for a StackOverflowException? I can’t get it to fail …

[Test]
public void Wait_RecursiveAdditionalContinueWith_Waits3()
{
    var start = new Task(() => { });
    var child = start.ContinueWith(ContinuationMethod3);

    start.Start();
    child.Wait();

    Assert.That(this.count, Is.EqualTo(100000000));
}

private void ContinuationMethod3(Task task)
{
    count++;
    if (this.count < 100000000)
    {
        var child = task.ContinueWith(ContinuationMethod3);
        child.Wait();
    }
}