0

我有一个需要处理大量消息的应用程序(例如:每秒 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
}
4

1 回答 1

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 秒钟。需要更多的工作,并且线程池通过创建另一个来帮助提供最大的帮助。对于您期望的请求数量,内存成为障碍只是时间问题。

于 2014-02-27T22:10:41.037 回答