views:

260

answers:

2

I think that nunit isn't function properly when threading code is involved:

Here's the sample code:

public class multiply
{
    public Thread myThread;
    public int Counter
    {
        get;
        private set;
    }
    public string name
    {
        get;
        private set;
    }
    private Object thisLock = new Object();
    public void RunConsolePrint()
    {
        //lock(thisLock)
        //{
       Console.WriteLine("Now thread " + name + " has started");
        for (int i = 1; i<= Counter; i++)
        {
                Console.WriteLine(name + ": count has reached " + i+ ": total count is "+Counter);
        }
        Console.WriteLine("Thread " + name + " has finished");
  //      }


    }
    public multiply(string pname, int pCounter)
    {
        name = pname;
        Counter = pCounter;
        myThread = new Thread(new ThreadStart(RunConsolePrint));
    }

}

And here's the test code:

        [Test]
        public  void Main()
        {
                counter=100;

               multiply m2=new multiply("Second", counter);
               multiply m1 = new multiply("First", counter);
                m1.myThread.Start();
                m2.myThread.Start();

        }

And the output is a sequential running of m1 and m2, which means that the loop in m1 is always execute first before m2, at least that's what my testing shows. I ran the tests a few times and I always get this.

Is this a bug? Or an expected behavior?

If I copy the above code to a console program and run, I can see the threading effect clearly.

I am using the test using TestDriven.net runner.

A: 

It's non-deterministic whether m1 or m2 starts executing first. If the counter executes fast enough, I wouldn't be surprised to see one of them finish before the other starts. Change the count to something very large (e.g. a million) and I'm pretty sure you'll see separate threads executing concurrently.

Any result is possible - what result are you seeing that suggests there's a bug?

Jon Skeet
I run the above test a few times, and I got consistent result-- m1 always executes first before m2
Ngu Soon Hui
That doesn't mean there's a bug. It may well just be a quirk of scheduling. Try making the task longer.
Jon Skeet
+1  A: 

The exact interleaving of two or more threads cannot really be predicted.

There are a couple of factors to consider for your example. First of all each thread will execute for its quantum before (potentially) getting switched to another thread. You can't expect thread switches to happen on any special place in your code. I.e. one thread might finish before the other one is started (especially since the task is relatively short in your case).

Secondly, since you're writing to the console, the threads are synchronized on that access. This also affects the interleaving.

The result also depends on the number of available core on your machine (as well as the general load on the machine when you run the code).

In short, you cannot predict how the two threads will run.

Brian Rasmussen