我有一个需要处理大量消息的应用程序(例如:每秒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
}
答案 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秒钟。需要做更多的工作,并且线程池最难通过创建另一个来帮助解决问题。随着您期望的请求数量,它只是时间问题直到内存成为障碍。