WPF RichTextBox内存泄漏
-
06-07-2019 - |
题
在我的应用程序中,我有很多在运行时动态创建的RichTextBox。我意识到应用程序有内存泄漏,这是由RichTextBox控件引起的。为了证明内存因控制而泄漏,我编写了以下测试方法:
for (int i = 0; i < 3000; i++)
{
Control rich = new RichTextBox();
pnl.Content = rich;
}
GC.Collect();
GC.WaitForPendingFinalizers();
pnl 是一个在Xaml代码中声明的ContentControl。
如果运行以下代码,则可以看到内存使用量正在快速增长。
任何想法如何解决问题? 我考虑过创建一个对象池,但这会使我的应用程序变得复杂,我宁愿避免使用它。
编辑:我已经添加了对垃圾收集器的调用,以证明对象没有被垃圾收集 - 无论是否调用GC收集方法,内存使用情况都没有改善。
请注意,在循环中调用 rich.Dispose
可以消除内存使用量的增长。
解决方案
在其他地方找到了它,就我的测试而言似乎是正确的。
创建FlowDocument时 相对昂贵的格式 也为其创建了上下文对象 它在StructuralCache中。当你 紧紧地创建多个FlowDocs 循环,创建一个StructuralCache 每个FlowDoc。我们打电话给你 Gc.Collect在循环结束时, 希望能恢复一些记忆力。 StructuralCache有一个终结器 发布此格式化上下文,但是 不是马上。终结者 有效地安排一个操作 发布上下文 DispatcherPriority.Background。
因此,RichTextBox(或FlowDocument)不会泄漏只是等待后台线程进行清理。当它完全运行谁知道。我希望这只是实现了一种强制立即清理的dispose方法。
其他提示
这并不表示您的应用程序存在内存泄漏,这表明您的应用程序使用了大量内存。如果 RichTextBox
控件在它们超出范围之后的某个时刻没有被释放(检测到托管对象上的内存泄漏是众所周知的困难和无法证明的话),那就是泄漏。
一种常见的误解,即一个物体超出范围会导致它被垃圾收集。这只是使符合条件的被收集。理论上,在应用程序终止之前,永远不会收集该对象。它与 RichTextBox
一起增长而不是与其他控件一起增长的事实并不表示 RichTextBox
中存在内存泄漏,这只表明它每个使用更多内存实例比其他控件。虽然这些信息可能有用,但在确定是否存在内存泄漏时无效。
我们在winforms 2.0中遇到了同样的问题,我们不得不购买第三方富文本控件。我想微软没有费心去解决它......
这解决了我的问题: http://blingcode.blogspot.com/2010/10 /memory-leak-with-wpfs-richtextbox.html
基本上为每个RichTextBox添加两个属性:) :) IsUndoEnabled = QUOT假QUOT;
关于你的编辑:
在循环终止并且已创建所有3000 RichTextBox
之后,您已添加了GC调用。
虽然我同意前一个在被一个新的替换之前没有在循环中被释放似乎很奇怪,但它是如此紧密的循环,GC可能没有机会“做它的东西” ;在循环终止之前。
我认为这不是一个好主意(但它在测试代码中应该没问题),但您是否尝试过在循环中移动GC调用?