我有很多线程,如果我让.NET运行时决定同时运行多少线程,它通常会触发OutOfMemoryException,因为操作非常繁重。
每次请求到达我的服务器时,我都需要运行一个线程。我想做一个ThreadPool.EnqueueWorkItem
但是说:请不要在给定时间内运行超过2个。在开始下一个之前等待其中一个完成。
在这种情况下,最佳做法是什么。
答案 0 :(得分:3)
使用ThreadPool.SetMaxThreads
方法。
来自MSDN:
设置可以处于活动状态的线程池的请求数 同时。超过该数字的所有请求将保持排队,直到 线程池线程变得可用。
重要说明:
如果托管公共语言运行库,例如通过Internet托管 信息服务(IIS)或SQL Server,主机可以限制或 防止更改线程池大小。更改时要小心 线程池中的最大线程数。虽然您的代码可能 好处,这些更改可能会对代码库产生负面影响 你用。将线程池大小设置得太大会导致性能下降 问题。如果同时执行的线程太多,则执行任务 切换开销成为一个重要因素。
此外,由于您提及OutOfMemoryException
,请尝试释放未使用的资源(例如,如果可用,请致电Dispose()
。)
<强>更新强>
正如@erikH评论的那样,重要注意到这种能力会限制整个线程池,但如果是一个较大的应用程序的一部分,这将限制一些繁重任务时的所有快速任务需要所有可用的线程池线程。
答案 1 :(得分:0)
我会写这样的东西
static int MAX_THREADS = 3;
static SemaphoreSlim _Semaphore = new SemaphoreSlim(MAX_THREADS, MAX_THREADS);
void ProcessRequest(Action action)
{
_Semaphore.Wait();
Task.Run(action)
.ContinueWith(t => _Semaphore.Release());
}
答案 2 :(得分:0)
你应该使用例如AsyncSemaphore primitive
这里是代码(未经测试):
static readonly AsyncSemaphore s_semaphore = new AsyncSemaphore( 2 );
static async Task EnqueueAction( Action act )
{
await s_semaphore.WaitAsync();
try
{
await Task.Run( act );
}
finally
{
s_semaphore.Release();
}
}