ThreadPool参数

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秒延迟的想法对于每个线程都令人沮丧.

谁能给我一些关于我为什么会看到这种行为的见解?

谢谢...

山姆

Ste*_*end 6

您需要将每个新线程传递给一个全新的对象.目前,它们都获得对主线程中相同对象的引用,即oTaskParameters

MyNumberMyThreadInfo构造函数上将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.