【问题标题】:ThreadPool Parameters线程池参数
【发布时间】:2010-09-29 13:25:34
【问题描述】:

我在将一个简单的线程池解决方案放入我的应用程序之前对其进行了测试,但我看到的结果对我来说没有意义。我有一个简单的表格,上面有一个按钮。此按钮启动以下循环:

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

谁能告诉我为什么我会看到这种行为?

谢谢...

山姆

【问题讨论】:

    标签: c# .net multithreading threadpool


    【解决方案1】:

    您需要向每个新线程传递一个全新的对象。目前他们都在主线程中获得了对同一个对象的引用,即oTaskParameters

    在将MyNumber 设置为MyThreadInfo 构造函数的参数后,试试这个:

    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
    }
    

    此更改意味着每个新线程都会获得一个不相交的 MyThreadInfo 实例,并且该线程的 id 已正确设置。

    仍然不能保证线程会按升序打印出它们的 id。您必须引入某种类型的 FIFO 队列/处理来强制执行。这个问题有详细的讨论ordering of thread execution using Threadpool.QueueUserWorkItem

    【讨论】:

    • 完美。我并不担心顺序,只是能够在线程发生时识别它们。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2015-02-28
    • 2018-12-04
    • 2015-03-21
    • 2019-01-29
    • 1970-01-01
    • 2010-09-18
    • 2011-07-11
    相关资源
    最近更新 更多