Sam*_*Sam 0 .net c# multithreading threadpool
在我将它放入我的应用程序之前,我正在测试一个简单的线程池解决方案,但我看到的结果对我来说没有意义.我有一个简单的表单,上面有一个按钮.此按钮启动以下循环:
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...");
}
Run Code Online (Sandbox Code Playgroud)
它正在调用的类看起来像这样.它有一个参数MyThreadInfo类,然后MyTestThread类在完成之前循环10秒.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
我希望在我的控制台/输出/调试日志中显示这样的结果.当我逐步完成应用程序时,我确实看到了这个:
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...
Run Code Online (Sandbox Code Playgroud)
但是,如果我全速运行应用程序,而不是单步执行代码或断点,则输出:
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...
Run Code Online (Sandbox Code Playgroud)
通过使代码有效的代码是什么?我注意到在循环中添加一个Thread.Sleep(1000)(1秒)会强制应用程序正确地标记线程,但我正在尝试开发一个快速的多线程应用程序,以及添加1秒延迟的想法对于每个线程都令人沮丧.
谁能给我一些关于我为什么会看到这种行为的见解?
谢谢...
山姆
您需要将每个新线程传递给一个全新的对象.目前,它们都获得对主线程中相同对象的引用,即oTaskParameters
MyNumber在MyThreadInfo构造函数上将settable设置为param 后尝试此操作:
for (int i = 1; i <= 5; i++)
{
MyThreadInfo oTaskParameters = new MyThreadInfo(i);
objTaskParameters.MyGuid = Guid.NewGuid();
ThreadPool.QueueUserWorkItem(new WaitCallback(objTask.ProcessDataForNTime), objTaskParameters);
}
MyThreadInfo(int i) : MyNumber(i)
{
// rest of construction logic
}
Run Code Online (Sandbox Code Playgroud)
此更改意味着每个新线程获取MyThreadInfo的不相交实例,并正确设置该线程的id.
仍然无法保证线程将按升序打印出它们的ID.您必须引入某种类型的FIFO队列/处理来强制执行该操作.对该问题进行了详细讨论ordering of thread execution using Threadpool.QueueUserWorkItem.