I am testing a simple threadpool solution before I put it in my application, but the results I am seeing do not make sense for me. I have a simple form with one button on it. This button starts the following loop:
private void button1_Click(object sender, EventArgs e)
{
MyTestThread oTask = new MyTestThread ();
MyThreadInfo oTaskParameters = new MyThreadInfo();
for (int i = 1; i <= 5; i++)
{
objTaskParameters.MyGuid = Guid.NewGuid();
objTaskParameters.MyNumber = i;
ThreadPool.QueueUserWorkItem(new WaitCallback(objTask.ProcessDataForNTime), objTaskParameters);
}
Console.WriteLine("All threads have been queued for processing...");
}
The class it is calling, looks like this. It has a parameters MyThreadInfo class, and then the MyTestThread class just loops for 10 seconds before finishing.
public class MyThreadInfo
{
public int MyNumber;
}
public class MyTestThread
{
public void ProcessDataForNTime(Object oParameters)
{
//We pass parameters
MyThreadInfo oThread = (MyThreadInfo)oParameters;
int threadNo = oThread.MyNumber;
Console.WriteLine("thread {0} started...", threadNo);
int iN = 10; //Delay for 10 seconds
DateTime dteStart = DateTime.Now;
do
{
System.Threading.Thread.Sleep(1000); //Wait a second before we look again
} while (dteStart.AddSeconds(iN) > DateTime.Now);
Console.WriteLine("thread {0} completed...", threadNo);
}
}
I would expect the results of this to display something like this in my console/output/debug log. When I step through the application, I do in fact see this:
thread 1 started...
thread 2 started...
thread 3 started...
thread 4 started...
thread 5 started...
All threads have been queued for processing...
thread 1 completed...
thread 2 completed...
thread 3 completed...
thread 4 completed...
thread 5 completed...
BUT, if I run the application at full speed, without stepping through the code or breakpoints, it outputs this:
All threads have been queued for processing...
thread 5 started...
thread 5 started...
thread 5 started...
thread 5 started...
thread 5 started...
thread 5 completed...
thread 5 completed...
thread 5 completed...
thread 5 completed...
thread 5 completed...
What is it about stepping through the code that makes it work? I did note that adding a Thread.Sleep(1000) (1 second) to the loop does force the application to label the threads correctly, but I’m trying to develop a fast multithreading application, and the idea of adding a 1 second delay for each thread is frustrating.
Can anybody give me some insight about why I am seeing this behaviour?
thanks…
Sam
You need to pass each new thread an entirely new object. Currently they all get a reference to the same object in the main thread, i.e.
oTaskParametersTry this, after making
MyNumbersettable as a param onMyThreadInfoconstructor:This change means that each new thread gets a disjoint instance of MyThreadInfo, with the id for that thread set appropriately.
There is still no guarantee that the threads will print out their ids in ascending order. You’d have to introduce some type of FIFO queue/processing to enforce that. There is a detailed discussion of that issue
ordering of thread execution using Threadpool.QueueUserWorkItem.