【发布时间】:2011-08-11 21:26:06
【问题描述】:
我的程序中一次运行 20 个线程,(创建 20 个等待它们完成,再启动 20 个),一段时间后我的程序变慢了。我需要释放任务或做一些特别的事情吗?如果是这样怎么办,如果不是这样的程序会变慢的常见原因是什么?
【问题讨论】:
-
它们是线程池线程,还是您明确管理它们?
标签: c# .net multithreading performance
我的程序中一次运行 20 个线程,(创建 20 个等待它们完成,再启动 20 个),一段时间后我的程序变慢了。我需要释放任务或做一些特别的事情吗?如果是这样怎么办,如果不是这样的程序会变慢的常见原因是什么?
【问题讨论】:
标签: c# .net multithreading performance
您可能要考虑直接使用ThreadPool,或通过Task Parallel Library(我的首选选项)。与生成自己的线程并反复阻塞它们相比,这可能是一种更好、更简单、更简洁的设计。
话虽如此,如果您的程序越来越慢,那么探查器可以提供极大帮助。没有看到代码,很难诊断。例如,根据您正在做的工作,您可能会导致 GC 随着时间的推移变得不那么高效,这可能会导致在 GC 中花费的时间百分比随着程序继续执行而攀升。分析应该可以很好地指示您的程序执行所花费的时间。
【讨论】:
Reed 的回答可能是处理您的问题的最佳方式;但是,如果您确实想自己管理线程,而不是使用 ThreadPool 或 TPL,我不得不问为什么要让 20 个线程死掉并再创建 20 个线程。创建线程是一个昂贵的过程,这就是线程池存在的原因。如果您持续拥有相同数量或最大数量的并行任务,则应该创建一次并重复使用它们。您可以使用信号量和互斥锁等锁定结构,并让线程在完成后等待,然后为它们提供新数据以使用并释放它们以再次继续。等待锁是一个非常便宜的操作——比重新创建线程便宜几个数量级。
例如,一个线程可能看起来像这样(伪代码):
while (program_not_ending)
{
wait_for_new_data_release; // Wait on thread's personal mutex
process_new_data;
resignal_my_mutex; // Cause the beginning of loop to wait again
release_semaphore_saying_I_am_done; // Increment parent semaphore count
}
然后父级将等待其信号量填满完成的 20 个线程,重置数据桶,并清除所有线程互斥体。
【讨论】: