【问题标题】:OutOfMemory Exception C# When working with threadsOutOfMemory 异常 C# 使用线程时
【发布时间】:2026-01-11 14:10:01
【问题描述】:

我有一项服务需要永久运行才能监控一台服务器。为此,我有 5 个任务需要服务完成(目前有 5 个,将有数百个)。

我创建了一个最多有 5 个线程的线程池。线程使用队列来获取任务,然后每个线程处理任务,然后再次将其入队。队列包含具有 5 个小属性的对象。

服务运行一段时间后,我在执行此操作的行收到 OutOfMemoryException:

ThreadPool.QueueUserWorkItem(currentJob.ProcessJob, (object)timeToWwait);

timeToWwait 是一个 int,我不再使用它了。

上下文是这样的:

        ThreadPool.SetMinThreads(0, 0);
        ThreadPool.SetMaxThreads(5, 5);
        while (true)
        {
            bool processJob = false;
            bool checkedFrontEnd = false;
            _qLock.EnterWriteLock();
            try
            {
                if (_jobQueue.Count > 0)
                {
                    currentJob = _jobQueue.Dequeue();
                    // currentJob.IsActive = true;
                    // processJob = true;
                }
            }
            finally
            {
                _qLock.ExitWriteLock();
            }
            ThreadPool.QueueUserWorkItem(currentJob.ProcessJob, (object)timeToWwait);
            //currentJob.ProcessJob((object)timeToWwait);


            _qLock.EnterWriteLock();
            try
            {
                _jobQueue.Enqueue(currentJob);
            }
            finally
            {
                _qLock.ExitWriteLock();
            }

请问您有什么建议吗?

【问题讨论】:

  • 请参阅常见问题解答,了解在您的问题中包含签名和在标题中包含标签。我已经修复了两次,但我从中获得的 2 个代表不值得再做一次。

标签: c# multithreading threadpool out-of-memory


【解决方案1】:

您的问题是您在后台任务有机会完成之前将 currentJob 实例排入队列。你会想做这样的事情:

        ThreadPool.QueueUserWorkItem((state) =>
                                         { 
                                             currentJob.ProcessJob();
                                             _qLock.EnterWriteLock();
                                             try
                                             {
                                                 _jobQueue.Enqueue(currentJob);
                                             }
                                             finally
                                             {
                                                 _qLock.ExitWriteLock();
                                             } 

                                         }
            );

【讨论】:

  • 非常感谢您对我的帮助。这确实解决了我的问题,感谢您的建议。我将使用这种方法。我只是在考虑一个新的设计,你的回答非常有帮助。
【解决方案2】:

看起来您可能希望仅在处理它的线程完成后再次将作业排入队列(到 jobQueue)。想象一下,池中只有 1 个线程,jobQueue 中只有 1 个作业,如果作业长时间运行,您的代码将在同一个作业上多次执行 ThreadPool.QueueUserWorkItem。另外,我认为您只想在 jobQueue 中有作业时执行 ThreadPool.QueueUserWorkItem (从上面的代码看来,无论如何它都会运行)。感谢您提出有趣的问题。

【讨论】:

  • 感谢您对我的问题感兴趣。你说的对。这真的解决了我的问题......终于。很有帮助。