0

我使用 QueueUserWorkItem() 函数来调用线程池。
我尝试了很多工作。(大约 30000)
但是通过任务管理器,我的应用程序在我按下开始按钮后只创建了 4~5 个线程。
我读了 MSDN,它说默认的线程限制数约为 500。
为什么我的应用程序中只创建了几个线程?
我很想加快我的应用程序的速度,我认为这个线程池是减慢我的应用程序的原因之一。

谢谢

4

3 回答 3

1

我想你可能误解了线程池的使用。产生线程和终止线程涉及 Windows 内核,并且是一项昂贵的操作。如果您不断需要线程来执行异步操作,然后将它们丢弃,它将执行许多系统调用。

所以线程池实际上是一组线程,它们被创建一次,而不是在完成任务时退出,实际上进入等待队列用户工作项的另一个项目。然后,线程池将根据您的进程同时需要多少线程来调整自己。如果您想对此进行测试,请编写以下代码:

for(int i = 0; i < 30000; i++)
{
    ThreadPool.QueueUserWorkItem(myMethod);
}

你会看到这将创建一大堆线程。也许不是 30000,因为当 ThreadPool 开始通过您的函数调用工作时,创建的一些线程将被重用。

于 2010-01-10T11:00:10.763 回答
1

了解线程池调度程序的工作原理很重要。它旨在根据机器的功能微调运行线程的数量。您的机器可能只能同时运行两个线程,双核 CPU 是当前标准。也许四个。

因此,当您将一堆线程倾倒在它的膝上时,它开始时只激活两个线程。其余的都在队列中,等待 CPU 内核可用。一旦这两个线程之一完成,它就会激活另一个线程。它每秒两次评估未完成的活动线程的情况。它粗略地假设这些线程正在阻塞,因此没有取得进展,并允许另一个线程激活。你现在有三个正在运行的线程。启动 500 个线程(默认的最大线程数)将花费 249 秒。

显然,这种行为说明了线程应该做什么才能适合作为线程池线程运行。它应该快速完成并且不要经常阻塞。请注意,对 I/O 请求的阻塞是单独处理的。

如果这种行为不适合您,那么您可以使用常规线程。它将立即开始运行,并与您的程序(和操作系统)中的其他线程竞争 CPU 时间。创建 30,000 个这样的线程是不可能的,没有足够的虚拟内存可用。一个 32 位操作系统在 2000 个线程以南的某个地方弹出,消耗了所有可用的虚拟内存。在分页文件用完之前,您可以在 64 位操作系统上获得大约 50,000 个线程。不建议在生产程序中测试这些限制。

于 2010-01-10T13:12:51.853 回答
0

线程池在那里,因此您可以避免为每个异步操作创建一个线程,因为线程很昂贵。如果您想要 30,000 个线程,您将为线程堆栈使用大量内存,并在执行上下文切换时浪费大量 CPU 时间。现在,如果您有 30,000 个 CPU 内核,那么创建那么多线程将是合理的……

于 2010-01-10T10:54:37.077 回答