.net winform treeview中的内存不足异常

时间:2013-04-22 12:55:35

标签: c# visual-studio-2010 listview treeview out-of-memory

我有一个树视图,根据树视图的项目,我有右侧的列表视图。所以几乎UI是我们的Windows资源管理器的一种外观。所以现在我遇到的问题是当我从右侧列表视图中删除大量对象时,左侧的树视图部分绘制(我可以说是小部分)。当我从VS IDE获得CLR激活时,它指向换行sampletree.EndUpdate();有一个例外的内存不足。当我在listview中添加下一个项目时,一切正常,我的意思是树视图完全被绘制 我得到的例外是

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

更新 我这样使用Font

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

这是否会产生任何问题

3 个答案:

答案 0 :(得分:3)

这种崩溃通常是由于泄漏GDI资源造成的。这通常是由于忘记在任何System.Drawing类对象上调用Dispose()方法而导致的。通常垃圾收集器会在您之后清理,但是,尤其是当您使用ownerdraw时,它可能不会经常运行以使您免于麻烦。当您消耗10,000个GDI对象时,Windows会拉动程序上的插件,结果就是kaboom。

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

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

答案 1 :(得分:1)

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

因此,作为解决方法,我要说尝试删除BeginUpdate()EndUpdate()来电。这确实意味着在您的节点更新时可能会出现一些视觉上的口吃,但从好的方面来说,它不会崩溃。这肯定是净胜利。

我在MSDN / Connect上找不到解决这个问题的任何内容,我现在还没有时间组建一个独立的测试用例,但我确实认为这是一个错误。在更高版本的Windows中处理TreeViews中的批量更新。

答案 2 :(得分:0)

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