首页 > 解决方案 > 记录 WinForms 应用程序状态

问题描述

我们有一个 WinForms 应用程序,它偶尔会抛出 OutOfMemory 异常。我们无法在任何开发机器上产生这个错误,但它偶尔会发生在我们的一些客户身上。我确信这不是由内存泄漏引起的,而是应用程序试图处理太多数据。这是有道理的,因为只有少数最大的客户遇到了这个问题。然而,问题是我不知道发生这种情况时他们在做什么。我们尝试过询问他们,答案类似于“它只是偶尔发生。”。我们有一个异常报告服务,它记录生产中发生的所有未处理的异常,但由于内存不足的工作原理,罪魁祸首不一定在调用堆栈中。对于这些问题,我从未在调用堆栈中看到我们的任何代码。

当抛出这些异常时,有没有办法确定应用程序中发生了什么?诸如打开了哪些窗口以及在这些窗口的控件中显示了哪些(多少)信息等信息。

以下是一些示例调用堆栈:

消息:引发了“System.OutOfMemoryException”类型的异常。System.Threading.WaitHandle.WaitAny(WaitHandle[] waitHandles, Int32 millisecondsTimeout, Boolean exitContext) System.Net.TimerThread.ThreadProc():436 System.Threading.ThreadHelper.ThreadStart_Context(对象状态):20 System.Threading.ExecutionContext.RunInternal (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx):112 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx):0 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback , 对象状态):43 System.Threading.ThreadHelper.ThreadStart():8

--

消息:引发了“System.OutOfMemoryException”类型的异常。System.Reflection.RuntimeAssembly.GetCodeBase(RuntimeAssembly 程序集,布尔copyName,StringHandleOnStack retString):-1 System.Reflection.RuntimeAssembly.GetCodeBase(布尔copyName):0 System.Reflection.RuntimeAssembly.GetName(布尔copyName):0 System.Reflection。 Assembly.GetName():0 System.Windows.Forms.ThreadExceptionDialog..ctor(异常 t):1033 System.Windows.Forms.Application+ThreadContext.OnThreadException(异常 t):57 System.Windows.Forms.Control.WndProcException(异常 e):0 System.Windows.Forms.Control+ControlNativeWindow.OnThreadException(异常 e):0 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam):58

标签: c#.netwinformsout-of-memory

解决方案


在这里可以找到对这不是什么的最佳解释之一

https://blogs.msdn.microsoft.com/ericlippert/2009/06/08/out-of-memory-does-not-refer-to-physical-memory/

基本思想是,在现代 Windows 操作系统中,计算机会在内存不足之前死机。它需要消耗硬盘的每个字节,并且它会交换得如此糟糕,以至于在实际内存耗尽之前很久就会注意到可怕的减速。

那么,什么是“OutOfMemoryException”,为什么会发生?嗯,有一些原因,有些与记忆有关,有些原因与记忆完全无关。

此错误的最常见来源:使用错误参数的 GDI+ 调用。来自 GDI+ 的任何错误,包括使用 System.Drawing 库,都会引发 OutOfMemoryException。这似乎是因为底层 API 没有向 .NET 提供失败原因的任何信息,因此 .NET 的创建者决定将它们全部称为 OutofMemoryException,现在他们为了兼容性而坚持使用它。尝试创建 0 大小的笔或创建带有错误格式标志的位图之类的事情会导致“内存不足”

.NET 可能将 OutOfMemory 用于 GDI 错误的原因是很多错误实际上与内存有关。仍然有数量有限的 GDI 句柄可用。它可能是几百万,但仍然有限,所以如果有东西泄漏了底层的 HBITMAP 或 HBRUSH 或 HPEN,最终它会用完,GDI 调用失败,你会得到一个异常。

我看到错误的另一个地方是使用任何 COM 接口。如果 COM 对象返回错误,您可能会收到 OutOfMemory 异常。我试图捕捉并处理这些错误。

对于跟踪,请查看与 GDI/System.Drawing 相关的调用。查看堆栈跟踪,它向您显示问题。

此外,不要假设“OutOfMemory”错误需要关闭应用程序。您应该能够从这些异常中恢复得很好,因为您并没有真正的内存不足。为什么客户甚至会看到此错误?


推荐阅读