.net Winform树视图中的内存不足异常

vet*_*ori 5 c# treeview listview out-of-memory visual-studio-2010

我有一个树视图,基于树视图的项目,我在右侧有列表视图。因此,几乎UI是我们Windows Explorer的一种外观。所以现在我面临的问题是,当我从右侧的列表视图中删除大量对象时,左侧的树形视图被部分绘制了(我可以说很小的一部分)。当我从VS IDE附加CLR响应时,它指向行sampletree.EndUpdate(); 除了内存不足。当我在列表视图中添加下一个项目时,一切都正常了,这意味着树形视图已完全绘制完毕,异常是

System.OutOfMemoryException occurred
  Message=Out of memory.
  Source=System.Drawing
  StackTrace:
       at System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
       at System.Drawing.Font.ToLogFont(Object logFont)
       at System.Drawing.Font.ToHfont()
       at System.Windows.Forms.Control.FontHandleWrapper..ctor(Font font)
       at System.Windows.Forms.OwnerDrawPropertyBag.get_FontHandle()
       at System.Windows.Forms.TreeView.CustomDraw(Message& m)
       at System.Windows.Forms.TreeView.WmNotify(Message& m)
       at System.Windows.Forms.TreeView.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m)
       at System.Windows.Forms.Control.WmNotify(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       at System.Windows.Forms.UserControl.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
       at System.Windows.Forms.Control.DefWndProc(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.TreeView.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, Int32 wParam, Int32 lParam)
       at System.Windows.Forms.Control.EndUpdateInternal(Boolean invalidate)
       at System.Windows.Forms.TreeView.EndUpdate()
Run Code Online (Sandbox Code Playgroud)

您是否知道为什么我的树状视图仅绘制了一个samll零件,而随后的修改又完全绘制了?代码段如下所示

 if( ( values != null ) &&
       ( values .OverallState != ToBeDeleted ) &&
       ( values .OverallState != .Deleted ) )
    {
       TreeView tree = this.TreeView;
       if( tree != null )
       {
          tree.BeginUpdate();
       }
       TryUpdate();
       TryPopulate();
       if( tree != null )
       {
          tree.EndUpdate();  // here exception coming
       }
    }
Run Code Online (Sandbox Code Playgroud)

更新 我正在以这种方式使用字体

case State.Modified:
                     NodeFont = new Font(TreeView.Font, FontStyle.Bold);
break;
Run Code Online (Sandbox Code Playgroud)

那有什么问题吗

Han*_*ant 3

这种崩溃通常是由于 GDI 资源泄漏造成的。这通常是由于忘记调用任何 System.Drawing 类对象上的 Dispose() 方法而引起的。通常垃圾收集器会在您之后进行清理,但是,特别是当您使用ownerdraw时,它可能不会经常运行以让您摆脱麻烦。当您消耗了 10,000 个 GDI 对象时,Windows 就会终止您的程序,结果就是 kaboom。

您可以从任务管理器轻松诊断此问题。查看 + 选择列并勾选句柄、USER 对象和 GDI 对象。在使用流程时,请观察流程中添加的那些列。稳步攀升的数字预示着 OOM Kaboom。

首先查看您的 DrawNode 事件处理程序,因为它可能会被频繁调用。但它也可能是由其他绘画代码引起的。确保使用 using语句创建绘图对象,如 Graphics、Pen、Brush、Font 等,以便保证它们在使用后被处理。从任务管理器获得的诊断信息会告诉您何时领先。

  • 看来问题(缺少 Dispose()、using{} 块)出在 .NET 内部绘图方法本身。问题出现在更改 NodeFont,而不是自定义节点绘制代码(GDI 对象增加 10,000)。另外,问题不是因为创建了多个 Font() 实例(您可以只创建一个),而是问题在于我们更改了多个节点的 NodeFont。(TreeView .NET 绘图代码正在内部创建 LOGFONT 或 HFONT,并且不会立即处理该对象。) (3认同)