【问题标题】:Preventing multithreaded apps from running out of memory防止多线程应用程序内存不足
【发布时间】:2009-05-27 20:21:45
【问题描述】:

我编写了一个小型的内部 C# 程序,它可以在各种文件格式之间进行批量转换,主要依赖于其他 API。目前,UI 会生成一个 BackgroundWorker(不是线程)来处理转换,然后在队列中填充请求,这些请求会在 worker 完成作业时清空。队列对象本身非常小(3 个字符串告诉工作人员该做什么)并且不会对程序的内存占用有很大贡献。我的内存管理相当严格(在完成图像后处理它们,并在某些时候手动进行垃圾收集。)不过,该程序往往一次使用大约 100 MB 的内存,并且使用大约 50%总 CPU 时间。似乎如果我天真地实现线程,它会很快耗尽系统内存(除非 CLR 做了某种我不知道的魔法。)

除了捕获 OutOfMemory 异常并回滚死掉的线程之外,是否有一种简单/有效的方法来生成线程以防止系统内存不足(看起来效率很低,但是如果不使用大量的内存)?

【问题讨论】:

  • 我们在讨论多少个线程?您提到了 UI 和一名工作人员……但这不应该是一个大问题;你在产生 很多 个线程吗?
  • 我目前有一个 BackgroundWorker 对象(不是线程)。我想添加更多以允许更高的 CPU 利用率但防止系统内存不足。就像我说的,一个工作人员的 UI 占用了 100 MB 的内存,所以即使再添加几个线程也可能是个问题。批处理作业通常可以超过 100 个文件。

标签: c# multithreading memory


【解决方案1】:

如果您使用ThreadPool.QueueUserWorkItem 产生转换,您将自动获得正在运行的线程数的限制。 ThreadPool 在内部对此进行管理,并在池线程可用时立即处理排队的调用。

【讨论】:

    【解决方案2】:

    限制队列大小,如果队列已满,则让发送者等待。不过,您必须凭经验找到正确的队列大小限制。

    【讨论】:

      【解决方案3】:

      内存不足异常可能很棘手,可能是由内存碎片引起的,实际上并不是内存不足。因此,它们可能很难追踪。

      来自瑞典 Microsoft 产品支持的 Tess (http://blogs.msdn.com/tess/) 收到了大量关于跟踪内存的帖子,其中内存将有助于此过程。

      您的应用的良好配置文件也会有所帮助。 JetBrains 和 AQTime 一样好用。

      【讨论】:

        【解决方案4】:

        对于图像处理应用程序来说,使用 100MB 内存并不算多。

        此外,在 .net 中,当您遇到 OutOfMemory 异常时,整个进程都会终止,您无法从中恢复。

        如果您需要比系统提供的更多内存(或者更准确地说是更多地址空间),您可以在使用时将内存分页进出或切换到 64 位。

        您可以限制队列大小以确保唯一的“重”内存用户是工作线程,您可以拥有多个工作线程,这会增加您的内存使用量但也会更快地清空队列,请记住在像这样的 CPU 密集型操作中,拥有比 CPU 内核更多的线程是低效的。

        你说的是“幼稚实现的线程”,多线程充满了陷阱——幼稚的实现将是低效的并且充满错误。

        【讨论】:

          猜你喜欢
          • 2017-11-09
          • 2021-11-20
          • 1970-01-01
          • 1970-01-01
          • 2012-03-17
          • 2012-07-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多