.net winform树视图内存不足异常



我有一个树视图和基于树视图的项目,我有listview在右边。UI几乎就是我们windows资源管理器的外观。所以现在我面临的问题是,当我从列表视图右侧删除大量对象时,左侧的树视图部分被绘制(我可以说的一小部分)。当我从VS IDE附加CLR异常时,它指向行sampletree. endpdate ();有一个异常,内存不足。当我在列表视图中添加下一个项目时,一切都正常了,我的意思是树视图是完全绘制的我得到的异常是

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()

你知道为什么我的树视图只画了一小部分,然后连续修改画满了吗?代码片段如下所示

 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
       }
    }

我用的字体是这样的

case State.Modified:
                     NodeFont = new Font(TreeView.Font, FontStyle.Bold);
break;

这有什么问题吗

这种崩溃通常是由GDI资源泄漏引起的。这通常是由于忘记在任何系统上调用Dispose()方法引起的。绘图类对象。通常垃圾收集器会在您之后进行清理,但是,特别是当您使用ownerdraw时,它可能不会经常运行以使您远离麻烦。当您使用了10,000个GDI对象时,Windows会关闭您的程序,结果是爆炸。

你可以很容易地从任务管理器诊断。查看+选择列并勾选句柄、USER对象和GDI对象。在使用您的流程时,请观察这些添加的列。一个稳步攀升的数字预示着OOM的爆炸。

首先查看您的DrawNode事件处理程序,因为它可能被频繁调用。但它也可能由其他绘画代码引起。确保你用using语句创建绘图对象,如图形、钢笔、画笔、字体等,这样它们在使用后就会被处理掉。从任务管理器中获得的诊断告诉您何时领先。

我刚刚遇到了完全相同的问题。它似乎只发生在XP之后的Windows系统中,并且,当我删除BeginUpdate()EndUpdate()调用时,它不会发生。

所以,作为一种变通方法,我会说尝试删除BeginUpdate()EndUpdate()调用。这确实意味着在更新节点时可能会出现一些视觉口吃,但是,从好的方面来说,它不会崩溃。那真是净赢了。

我在MSDN/Connect上没有发现任何解决这个问题的东西,我现在没有时间把一个独立的测试用例放在一起,但我确实认为这是在Windows的后续版本中处理TreeViews批量更新的错误。

您可以在更改节点字体或颜色后使用System.GC.Collect()强制垃圾收集器

最新更新