- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
[更新,见底部!]
我们托管 WPF 的 WinForms 应用程序中存在内存泄漏 FlowDocumentReader
在 ElementHost
.我在一个简单的项目中重新创建了这个问题并添加了下面的代码。
应用程序的作用
当我按下 button1
:
UserControl1
其中只包含一个 FlowDocumentReader
创建并设置为 ElementHost
的 Child
FlowDocument
从文本文件创建(它只包含一个 FlowDocument
和一个 StackPanel
和几千行 <TextBox/>
)FlowDocumentReader
的 Document
属性设置为此 FlowDocument
FlowDocument
正确。正如预期的那样,使用了大量内存。
button1
再次单击,内存使用量增加,并且每次重复该过程时都会增加!尽管使用了大量新内存,但 GC 没有收集!没有不应该存在的引用,因为:button2
其中集 elementHost1.Child
为 null 并调用 GC(参见下面的代码),另一个奇怪的事情发生了 - 它不会清理内存,但如果我继续点击它几秒钟,它最终会释放它! ElementHost
来自
Controls
收藏,
Disposing
它,将引用设置为空,然后调用 GC 不会释放内存。
button1
被多次点击,内存使用量不应继续上升 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Documents;
using System.IO;
using System.Xml;
using System.Windows.Markup;
using System.Windows.Forms.Integration;
namespace WindowsFormsApplication7
{
public partial class Form1 : Form
{
private ElementHost elementHost;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string rawXamlText = File.ReadAllText("in.txt");
using (var flowDocumentStringReader = new StringReader(rawXamlText))
using (var flowDocumentTextReader = new XmlTextReader(flowDocumentStringReader))
{
if (elementHost != null)
{
Controls.Remove(elementHost);
elementHost.Child = null;
elementHost.Dispose();
}
var uc1 = new UserControl1();
object document = XamlReader.Load(flowDocumentTextReader);
var fd = document as FlowDocument;
uc1.docReader.Document = fd;
elementHost = new ElementHost();
elementHost.Dock = DockStyle.Fill;
elementHost.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
Controls.Add(elementHost);
elementHost.Child = uc1;
}
}
private void button2_Click(object sender, EventArgs e)
{
if (elementHost != null)
elementHost.Child = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
}
<UserControl x:Class="WindowsFormsApplication7.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<FlowDocumentReader x:Name="docReader"></FlowDocumentReader>
</UserControl>
ElementHost
,每次按下按钮时都会处理并重新创建它。虽然这确实有点帮助,但从某种意义上说,当您发送垃圾邮件单击 button1 时内存会上下波动,而不是仅仅上升,但它仍然没有解决问题 - 内存总体上升,并且在以下情况下不会被释放表格已关闭。所以现在我悬赏了。
Controls.TextBox
和 16125 Controls.TextBoxView
两者都 Root 于 16125 Documents.TextEditor
根植于终结队列的对象 - 请参阅此处:
ElementHost
的纯 WPF 应用程序中再次遇到了这个问题。或
FlowDocument
,所以回想起来,标题是误导性的。正如 Anton Tykhyy 所解释的,这只是 WPF
TextBox
的一个错误。本身,它没有正确处理它的
TextEditor
.
TextBoxes
的控件实例时,我这样做(在控件的代码隐藏中):
var textBoxes = FindVisualChildren<TextBox>(this).ToList();
foreach (var textBox in textBoxes)
{
var type = textBox.GetType();
object textEditor = textBox.GetType().GetProperty("TextEditor", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(textBox, null);
var onDetach = textEditor.GetType().GetMethod("OnDetach", BindingFlags.NonPublic | BindingFlags.Instance);
onDetach.Invoke(textEditor, null);
}
FindVisualChildren
是:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
TextBox
应该做的。最后我也打了
GC.Collect()
(并非绝对必要,但有助于更快地释放内存)。这是一个非常丑陋的解决方案,但它似乎解决了问题。没有了
TextEditors
卡在完成队列中。
最佳答案
我在这里找到了这篇博文:Memory Leak while using ElementHost when using a WPF User control inside a Windows Forms project
所以,在你的 Button2 点击事件中试试这个:
if (elementHost1 != null)
{
elementHost1.Child = null;
elementHost1.Dispose();
elementHost1.Parent = null;
elementHost1 = null;
}
Form1
.有了这个,我尝试打开你的表单大约 20 次,总是点击 Button1 然后 Button2 然后关闭表单,内存使用量保持不变。
ElementHost
的一个错误控制。
Form1
:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
m_uc1 = new UserControl1();
elementHost1.Child = m_uc1;
}
private UserControl1 m_uc1;
private void button1_Click(object sender, EventArgs e)
{
string rawXamlText = File.ReadAllText(@"in.txt");
var flowDocumentStringReader = new StringReader(rawXamlText);
var flowDocumentTextReader = new XmlTextReader(flowDocumentStringReader);
object document = XamlReader.Load(flowDocumentTextReader);
var fd = document as FlowDocument;
m_uc1.docReader.Document = fd;
flowDocumentTextReader.Close();
flowDocumentStringReader.Close();
flowDocumentStringReader.Dispose();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (elementHost1 != null)
{
elementHost1.Child = null;
elementHost1.Dispose();
elementHost1.Parent = null;
elementHost1 = null;
}
}
关于c# - ElementHost + FlowDocument = GC 不工作,内存不断增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14757527/
我正在使用非 WPF 应用程序,因此我只能创建 WPF 用户控件。我解决这个问题的方法是将我的窗口创建为用户控件,然后我创建了一个通用的 winform 来托管 wpf 用户控件(使用 Element
我在 WinForms 容器中托管 WPF UserControl。现在,我希望能够为 UserControl 设置主题/外观。为此,我有几个定义“皮肤”的资源词典。当我的应用程序启动时,我创建了一个
是否可以从 WPF 用户控件(即 ElementHost 的子级)显示模态窗口,并将模态窗口的所有者/父级设置为包含表单控件? 我猜你不能这样做,因为 Owner 属性采用 Window 的一个实例,
我有一个小的 WPF 控件,它有一个 TextBlock,TextWrapping 设置为 Wrap。我试图在现有的 WinForms 应用程序中托管它。我将 ElementHost 停靠在表单顶部,
我正在 WinForms 应用程序一侧构建一组 WPF 控件,以便最终可以将整个项目转换为 WPF。我正在使用 WinForms ElementHost 模块并在其中设置我的 WPF 控件。 这是我的
我有一个 Form(winform),它包含 Elementhost。在运行时,我将我的 WPF 用户控件托管到此 elementhost。我对 elementhost 使用了 AutoSize =
我对这个 ElementHost 有很多问题。有人可以看看我有什么,让我知道发生了什么或为什么没有显示吗?一切似乎都正常,只是我看不到 ElementHost 在屏幕上显示/刷新(用户控件)。 测试.
我需要在 Winform 用户控件上托管 WPF 控件。为此,我使用了 ElementHost 控件。当我运行 Ants Memory profiler 时,我知道 ElementHost 控件中存在
我在 ElementHost 内的 Winforms 项目中有一个 WPF 控件(ICSharpCode.AvalonEdit.TextEditor)。 我已经通过调试器确认 TextEditor 实
我试图在 WinForms 应用程序中使用 WPF 文本框,同时将与 WPF 相关的详细信息完全封装在另一个程序集中,但窗体编辑器并没有使它变得简单。 也就是说,Child 访问器总是被分配给一个新的
我正在编写一个程序来在 C# 中实现 COM 组件。该组件也提供了一个 UI 组件。为了便于实现组件的 future 添加,我决定使用 WPF 在 Xaml 中编写 UI,并将其包装在 Element
我有一个 WinForms 控件,里面有一个 TableLayoutPanel,它包含多个 ElementHosts,每个 ElementHost 都包含一个 WPF 控件。 一切正常,除非控件的大小
我有 UserControl,它位于 ElementHost 中. 它包含 DataGrid当用户按下回车键或双击该行时,将显示新窗口(无模式),并且当该窗口关闭时,带有 ElementHost 的窗
我使用 WPF 互操作性在 WinForms 表单中托管 WPF 用户控件。 除了丑陋的文本渲染外,一切正常: -- 这是 WPF 窗口上的简单标签: WPF Window htt
我有一个 Windows 窗体应用程序,它有一个包含 WPF 用户控件的 ElementHost... 在我的 WPF 中,我有一个非常简单的 ListView:
对于生产应用程序,我们希望在 Windows 窗体应用程序的 ElementHost 内显示 DatePicker,但我们遇到了 SelectedDate 和 CurrentDate 不可读的问题,因
我有一个 winforms 应用程序,我想向其添加 WPF 用户控件。问题是当我运行程序时,WPF 用户控件不响应鼠标事件。我可以在控件中切换并使用键盘就好了,但是控件不响应鼠标点击(当您将鼠标悬停在
长期潜伏者和自学 OOP 和 c# 的大部分人都感谢这里的伟人。我 99% 的问题似乎都是通过全网搜索找到的,但我仍然被这个问题困住了。 我的问题是我有一个自定义 GUI,我在其中堆叠托管 WPF 用
我在个人库中使用 WPF 用户控件。这些库包含在我的 WPF 和 WindowsForms 程序中。现在我的 UserControl 必须显示一个新的 (WPF) 窗口。在新窗口中,我想设置所有者。我
[更新,见底部!] 我们托管 WPF 的 WinForms 应用程序中存在内存泄漏 FlowDocumentReader在 ElementHost .我在一个简单的项目中重新创建了这个问题并添加了下面
我是一名优秀的程序员,十分优秀!