线程池参数

发布于 2024-09-25 13:23:08 字数 2200 浏览 3 评论 0原文

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你在我安 2024-10-02 13:23:08

您需要向每个新线程传递一个全新的对象。目前,它们都在主线程中获得对同一对象的引用,即 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 队列/处理来强制执行此操作。 使用 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 on MyThreadInfo constructor:

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
}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文