ThreadPool线程需要等待

时间:2013-07-17 09:33:30

标签: c# .net task-parallel-library threadpool

我有一个需要处理大量消息的应用程序(例如:每秒2000个)。业务需求要求我不要立即处理消息,而是等待2秒钟来处理每条消息。我现在正在做的是通过Task.Factory.StartNew为每个消息从线程池中分离一个线程,并在池中的线​​程内执行“等待2秒”作业。问题是当消息加载真的很高时,我总是得到OutOfMemory异常,尽管根据Windows操作系统的任务管理器,内存消耗实际上并不高。但是,如果我不在线程内等待,那么一切都还可以。

我的猜测是,当消息加载很高时,线程池线程不足以处理所有消息。因此,越来越多的消息排队等待处理,当队列大小变得非常大时,会导致OOM异常。已经尝试过ThreadPool.SetMaxThreads和ThreadPool.SetMinThreads到很高的数字,但仍然无法正常工作。有什么建议吗?

代码如下所示:

 ThreadPool.SetMaxThreads(32768, 32768);
 ThreadPool.SetMinThreads(2500, 2500);

public void HanldeMessage(string message)
{
     Task.Factory.StartNew(() => DoWork(message))
}

public void DoWork(string message)
{
   Thread.Sleep(2000);
   // do some work to message
}

1 个答案:

答案 0 :(得分:2)

试试这个。你需要.NET 4.5。

private static void HandleMessage(string message)
{
    DoWork(message);
}

private static async Task DoWork(string message)
{
    await Task.Delay(2000); // instead of thread.Sleep

    // do some work...
    Console.WriteLine(message);
}

而不是在thread.sleep上阻塞,这应该有效地将线程返回池2秒,然后返回执行。

我建议你不要阻止线程,特别是在处理可能需要数千个的场景时。我还建议你不要设置ThreadPool.MaxThreads / MinThreads。你在这里经历了很多滥用。

每个线程占用1MB的堆栈空间。我打赌你看到OOM异常的原因是因为你创建了太多的线程,而不是因为排队的请求来创建线程。你上面的情况很可怕,因为经过所有的工作来创建一个线程,它只是坐下来腐烂2秒钟。需要做更多的工作,并且线程池最难通过创建另一个来帮助解决问题。随着您期望的请求数量,它只是时间问题直到内存成为障碍。