c# - 记录 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
解决方案
在这里可以找到对这不是什么的最佳解释之一
基本思想是,在现代 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”错误需要关闭应用程序。您应该能够从这些异常中恢复得很好,因为您并没有真正的内存不足。为什么客户甚至会看到此错误?
推荐阅读
- python - 安装 PyQt5 时出错
- java - notify 会立即调用等待线程吗?
- javascript - 如何过滤数组内的对象?
- node.js - 在 nodejs 中使用 async-await 和 Promise 时无法以所需的顺序获得结果
- vlang - 如何调用 C 例程“lseek”?
- pine-script - 如何翻转仓位?strategy.close() 和 strategy.exit()
- firebase - Google Cloud Firestore 'in' Operator 解决方法
- php - 将自定义产品价格乘以 WooCommerce 购物车中的数量
- mysql - Mysql插入具有相同表计数的值
- javascript - 在 Vue 中操作元素