线程池参数
在将一个简单的线程池解决方案放入我的应用程序之前,我正在测试它,但我看到的结果对我来说没有意义。我有一个简单的表格,上面有一个按钮。该按钮启动以下循环:
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...");
}
它正在调用的类,如下所示。它有一个参数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);
}
}
我希望结果会在我的控制台/输出/调试日志中显示类似的内容。当我单步执行该应用程序时,我实际上看到了这一点:
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...
但是,如果我全速运行该应用程序,而不单步执行代码或断点,它会输出以下内容:
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...
单步执行使其工作的代码是什么?我确实注意到,向循环添加 Thread.Sleep(1000) (1 秒)确实会强制应用程序正确标记线程,但我正在尝试开发一个快速的多线程应用程序,以及添加 1 秒延迟的想法对于每个线程来说都是令人沮丧的。
有人可以告诉我为什么我会看到这种行为吗?
谢谢...
萨姆
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要向每个新线程传递一个全新的对象。目前,它们都在主线程中获得对同一对象的引用,即
oTaskParameters
在将
MyNumber
设置为MyThreadInfo
上的参数后尝试此操作构造函数:此更改意味着每个新线程都会获得一个不相交的 MyThreadInfo 实例,并适当设置该线程的 id。
仍然不能保证线程会按升序打印出它们的 id。您必须引入某种类型的 FIFO 队列/处理来强制执行此操作。
使用 Threadpool.QueueUserWorkItem 进行线程执行顺序
对此问题进行了详细讨论。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.
oTaskParameters
Try this, after making
MyNumber
settable as a param onMyThreadInfo
constructor: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
.