c#, WPF,异步GUI更新和内存泄漏

本文关键字:内存 泄漏 更新 GUI WPF 异步 | 更新日期: 2023-09-27 18:12:13

private delegate void UpdateTextBoxDelegate(System.Windows.DependencyProperty dp, Object     value);
..
UpdateTextBoxDelegate updateTextDelegate = new UpdateTextBoxDelegate(textBox1.SetValue);
..
foreach(..)
    Dispatcher.Invoke(updateTextDelegate, System.Windows.Threading.DispatcherPriority.Background, new object[] { TextBox.TextProperty, content.ToString() });

这东西漏了。随着任务的出现,我正在更新一个带有一些进度信息的GUI,它工作得很好,但最后一行中的content.ToString()泄漏了。我只能推测,通过Dispatcher有一个对该字符串的引用,直到它被销毁(当我关闭保存它的对话框时,内存将被释放)。很明显,只是通过观察内存使用模式(开始很慢,然后随着字符串变大,趋向于10meg的增量),字符串吞噬了内存,我也做了一个挂起进程的转储(内存不足),并使用windbg进行调试。一些跟踪将它放入许多char[]和GUI框架文本框等。)当我显式SetValue,甚至异步,为什么旧的内容不适合垃圾收集?

建议吗?: -)

c#, WPF,异步GUI更新和内存泄漏

首先,如果你已经释放了引用,你不应该担心内存的问题,把剩下的留给垃圾收集器去做它的工作。

其次,您可以做的是通过限制对象在更高代中的访问来简化GC的工作。

如果一个对象可以在第一次扫描中被清除,那么GC更喜欢。

更多关于垃圾收集的基础知识:世代

未被垃圾收集器收集的问题是对象

的生成

gen 0在它们未被引用后在第一次扫描中被清除

,但如果在垃圾收集清理内存时仍然引用

,则same将提升为gen1。

到第2代,等等

所以为了最小化提升你可以将值复制到一个局部变量

例子
foreach(..)
{
    string value = content.ToString();
    Dispatcher.Invoke(updateTextDelegate, DispatcherPriority.Background, new object[] { TextBox.TextProperty,  value });
}

忘掉这个吧,答案是使用StringBuilder而不是普通的字符串来构建。