6

我有一个树视图,并且基于树视图的项目,我在右侧有列表视图。所以几乎 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()

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

 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;

这有什么问题吗

4

3 回答 3

3

这种崩溃通常是由 GDI 资源泄漏引起的。这通常是由于忘记在任何 System.Drawing 类对象上调用 Dispose() 方法引起的。通常垃圾收集器会在你之后进行清理,但是,尤其是当你使用 ownerdraw 时,它可能不会经常运行,无法让你远离麻烦。当您消耗了 10,000 个 GDI 对象时,Windows 会在您的程序上拔掉插头,结果就是 kaboom。

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

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

于 2013-04-22T14:37:17.730 回答
1

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

因此,作为一种解决方法,我会说尝试删除BeginUpdate()andEndUpdate()调用。这确实意味着在更新节点时可能会出现一些视觉卡顿,但从好的方面来说,它不会崩溃。这肯定是一场净胜。

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

于 2013-05-01T09:45:23.063 回答
1

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

于 2019-03-22T14:17:15.277 回答