24

如果我对 ThreadPool 工作方式的理解是正确的,那么它的目的之一就是限制一个进程中可以在给定时间创建的工作线程的数量。例如,如果您将 MaxThreads 设置为 5,然后调用 QueueUserWorkItem 30 次,则会向 ThreadPool 发出 30 个请求,但其中只有 5 个请求会被新线程处理,而其他 25 个请求将被添加到队列中并在先前的请求完成并且现有线程可用时一次提供一个服务。

然而,在下面的代码中,对 Thread.Sleep(-1) 的调用保证 DoSomething() 方法永远不会返回,这意味着当前线程永远不会对后续请求可用。

但是我对 ThreadPool 工作方式的理解是不正确的,因为如果它是正确的,下面的代码将只打印数字 0-4,而不是 0-29。

有人可以解释一下 ThreadPool 是如何工作的,以及为什么下面的代码没有做我认为应该做的事情吗?

    static void DoSomething(object n)
    {
        Console.WriteLine(n);
        Thread.Sleep(-1);
    }

    static void Main(string[] args)
    {
        ThreadPool.SetMaxThreads(5, 5);
        for (int x = 0; x < 30; x++)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(DoSomething), x);
        }
        Console.Read();
    }
4

4 回答 4

18

ThreadPool.SetMaxThreads(5, 5)

means the number of active thread is 5 (if you have more than 5 cpu core), does not mean that the ThreadPool can only create 5 threads. The ThreadPool maximum number of threads = CPU Core * 250.

After Thread.Sleep, the thread is inactive, so it will not affect the execution of other threads.

于 2013-01-25T05:35:45.030 回答
4

但是我对 ThreadPool 工作方式的理解是不正确的,因为如果它是正确的,下面的代码将只打印数字 0-4,而不是 0-29。

是的,您的假设非常正确。

由于您在 ThreadPool 中排队了 30 个作业,并且这些作业将无限期地休眠,它们永远不会完成,ThreadPool 类将等待一定的时间间隔来创建新线程,但不会超过最大线程数。

笔记

Console.Read() 使您的后台线程保持活动状态。

文章

来自 MSDN

许多应用程序创建的线程会花费大量时间处于睡眠状态,等待事件发生。其他线程可能会进入睡眠状态,只是为了定期唤醒以轮询更改或更新状态信息。线程池通过为您的应用程序提供由系统管理的工作线程池,使您能够更有效地使用线程。一个线程监视排队到线程池的几个等待操作的状态。当等待操作完成时,线程池中的一个工作线程执行相应的回调函数。


当所有线程池线程都已分配给任务时,线程池不会立即开始创建新的空闲线程。为了避免不必要地为线程分配堆栈空间,它会每隔一段时间创建新的空闲线程。该时间间隔目前为半秒,但在 .NET Framework 的未来版本中可能会发生变化。


托管线程池中的线程是后台线程。也就是说,它们的 IsBackground 属性为真。这意味着 ThreadPool 线程不会在所有前台线程都退出后保持应用程序运行。

于 2013-01-25T05:36:48.733 回答
2

可能是 Thread.Sleep(-1) 没有按照您的预期进行。

参数 Int32:线程被阻塞的毫秒数。指定零 (0) 表示应该挂起该线程以允许其他等待线程执行。指定 Infinite 无限期地阻塞线程。

http://msdn.microsoft.com/en-us/library/d00bd51t.aspx

您应该查看 Tasks, http: //msdn.microsoft.com/en-us/library/dd235608.aspx将其视为 Threadpool 2.0

于 2013-01-25T04:24:25.523 回答
0

通常,ThreadPool 创建的线程数等于 CPU 内核数。没有必要创建更多线程,因为核心一次只能处理一个线程。但是,当排队到 ThreadPool 的任务执行时间超过 0.5 秒时,ThreadPool 会创建一个额外的线程来处理队列中的剩余任务。因此,如果您将大量繁重的任务排队到 ThreadPool 中,它将创建大量额外的线程来模拟多任务处理并“并行”执行所有任务。但是总执行时间与没有额外线程的情况相同,而且,因为创建线程是相当繁重的操作,所以它会更少。这就是为什么建议将 ThreadPool 用于小型任务,以避免创建实际上不会带来任何优势的额外线程。

您可以在Albahari 的文章中阅读有关 ThreadPool 的更多信息。实际上,他在那里有很多关于线程的文章。

于 2013-01-25T04:29:48.570 回答