【问题标题】:Properly handle OutOfMemoryException throwing in different line every time正确处理每次抛出不同行的 OutOfMemoryException
【发布时间】:2013-10-10 02:12:47
【问题描述】:

我的 c# 应用程序可以不时抛出 OOM(它允许用户使用 SQL limit 命令检索数据而无需使用 SQL),我只需要正确处理它。 MessageBox 包含使用 limit 的建议就足够了。

问题是 OOM 每次都在不同的行中引发(在同一行中检索相同的数据,但新数据 - 新的异常点):有时 GDI+ 没有可用内存来进行绘制,有时是 SQL 连接器失败,有时是包装类之一。不同的行,不同的类,不同的事件处理程序,甚至不同的匿名方法。它并不像听起来那么糟糕,类层次结构是相当合法的,但我真的不能让它简单到只使用一个(甚至两个)try/catch 块(应用程序是多线程的顺便说一句)。

AppDomain.CurrentDomain.UnhandledException/Application.ThreadException 是没有选择的(来不及处理)。

有没有办法正确处理应用程序抛出的第一个OOM(“第一个”,因为在数据检索入口点周围捕获OOM会导致另一个OOM,例如由于尝试清除SortableBindingList)?以这样一种方式处理它,当您试图强制 GC 做一些工作时,不会在其他地方分配内存?

【问题讨论】:

  • 您是否在分离调试器的情况下运行发行版程序? GC 不会收集对象(即使你用GC.Collect() 明确告诉它这样做),因为调试器本身会保持对象处于活动状态(否则像监视屏幕之类的东西不会可靠地工作,所以只要一个对象可以可能在不会被收集的监视窗口中使用)。如果没有附加调试器,是否还会出现 OOM 错误?
  • 由于非内存原因,GDI+ 也会抛出OutOfMemoryException。如果您不处置 GDI 对象,您将耗尽 GDI 资源,并且由于内存压力,这些资源不会像大型对象那样自动收集。

标签: c# garbage-collection out-of-memory


【解决方案1】:

您似乎认为 OOM 是因为垃圾收集器没有完成它的工作。更有可能是因为您的应用程序使用了过多的内存(或内存碎片过多)。

如果您的应用程序的内存使用量是由用户输入决定的,并且如果您无法限制该用户输入以防止 OOM,那么我建议在单独的 AppDomain 中执行失败的代码。如果该 AppDomain 失败,那么您的原始 AppDomain 仍将处于良好状态以处理失败并通知用户“不要再这样做了”。

【讨论】:

  • 不,GC 做得很好。这个想法是OOM是可以接受的,由于首先提高点移动性并且需要在任何捕获块对策中分配新的内存块,我只是无法正确处理它。想一想,我相信单独的 AppDomain 应该可以解决问题。讨厌的把戏,但似乎值得,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 2014-09-20
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 2012-06-27
相关资源
最近更新 更多