WPF 窗口不会释放其资源,直到程序终止

2024-03-25

我一直在阅读有关 WPF 内存处理的内容,并跟踪了前 5 个和前 8 个内存泄漏陷阱,但在我目前的情况下没有任何帮助。

我的软件有一个问题,WPF 在程序终止之前不会释放内存。如果我永远让它消失,无论我做什么都会导致 OutOfMemoryException。我已经设法在一个小样本中隔离该问题,以展示它如何不释放其内存,即使我不再使用它。这是我重现问题的方法:

我创建了 2 个项目,1 个控制台程序和 1 个 WPF 应用程序。在我的 WPF 应用程序中,我有一个 MainWindow.xaml,其中没有任何内容:

<Window x:Class="MemoryLeakWpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MemoryLeakWpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Loaded="MainWindow_OnLoaded">
    <Grid>

    </Grid>
</Window>

我确实订阅了 Loaded 事件,我用它来立即关闭窗口,可以在此处的 .cs 文件中看到:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Debug.WriteLine("Constructing",GetType().Name);
    }

    ~MainWindow()
    {
        Debug.WriteLine("Deconstructing", GetType().Name);
    }

    private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        Close();
    }
}

我还在构造函数和解构函数中添加了调试行,以便我可以跟踪它的创建和丢弃时间。然后,我在 WPF 应用程序中创建一个 Controller 类,它代表此 WPF 类库的入口点,该类库具有创建和显示窗口的方法:

public class Controller
{
    public void Execute()
    {
        MainWindow window = new MainWindow();
        window.ShowDialog();
        Debug.WriteLine("Constructing", GetType().Name);
    }

    ~Controller()
    {
        Debug.WriteLine("Deconstructing", GetType().Name);
    }
}

这里我还添加了调试跟踪线。我没有 App.xaml,因为此 WPF 项目在其属性中设置为类库。那是 WPF 部分。在控制台项目中,我将以下代码添加到我的主类中:

[STAThread]
static void Main(string[] args)
{
    for (int i = 0; i < 100; i++)
    {
        Controller controller = new Controller();
        Console.WriteLine("Test " + i);
        controller.Execute();
    }

    Console.WriteLine("Pressing enter will close this");
    Console.ReadLine();
    Debug.WriteLine("Party is over, lets leave");
}

所以基本上的设置是我有一个想要显示对话框的控制台类。它为 WPF 应用程序创建控制器并调用 Execute。控制器显示加载完成后立即关闭的窗口。然后控制台类创建一个新的控制器来重新执行该过程。现在,这是我在输出中看到的内容:

MainWindow: Constructing
Controller: Constructing
MainWindow: Constructing
Controller: Constructing
Controller: Deconstructing
MainWindow: Constructing
Controller: Constructing
Controller: Deconstructing
MainWindow: Constructing
Controller: Constructing
Controller: Deconstructing
MainWindow: Constructing
Controller: Constructing
Controller: Deconstructing

控制器正在构造和解构,但窗口却没有。但是,当 for 循环完成并且我按 Enter 键让程序运行时,我得到以下结果:

Party is over, lets leave
MainWindow: Deconstructing
Controller: Deconstructing
MainWindow: Deconstructing
Controller: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing
MainWindow: Deconstructing

突然间,MainWindow 的所有实例现在都在解构,但只有在程序运行完时,而不是在我们丢弃 for 循环中的引用时。这意味着在我们的程序中,在发生 OutOfMemoryException 之前,我们只能打开有限次数的窗口。

但价值百万美元的问题是:如何说服 WPF 在程序运行时而不是在程序关闭时释放其内存?


您声称自己是[STAThread]但你还没有消息泵。如果没有消息泵,你就不是真正的 STA。在这种特殊情况下,这意味着 WPF 永远没有机会清理其资源。 WPF 可能会将消息发布到消息队列,但从未被拾取。

由于 WPF 是一个多线程系统,它必须执行后台操作,包括多个线程之间的同步。为了返回主线程,它使用Dispatcher您尚未正确设置的基础设施。

要解决您的问题,您需要运行 WPFDispatcher在 STA 线程上,不实现您自己的循环。

另外,为了完整起见,链接到相关帖子 https://stackoverflow.com/questions/63586833/window-object-not-released-after-being-closed-even-after-gc-collect-and-waitfor这把我带到了这里。确保在设置调度程序基础设施后测量正确的内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF 窗口不会释放其资源,直到程序终止 的相关文章

  • 专家 C#/.Net/WPF 开发人员应该了解哪些知识? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • WPF中ViewModel是否应该继承DependencyObject?

    我尝试创建一个简单的UserControl在 WPF 中使用 MVVM 现在我需要为UserControl 所以我尝试在中创建依赖属性UserControlViewModel 我不想处于代码隐藏状态 为了创建依赖属性UserControlV
  • 消息框按钮文本

    我环顾四周 似乎所有内容都可以在消息框中编辑 禁止按钮上的文本 WPF http en wikipedia org wiki Windows Presentation Foundation C MessageBox Show Generic
  • 什么是内部类的合成反向引用

    我正在寻找应用程序中的内存泄漏 我正在使用的探查器告诉我寻找这些类型的引用 但我不知道我在寻找什么 有人可以解释一下吗 Thanks Elliott 您可以对 OUTER 类进行合成反向引用 但不能对内部类实例进行合成 e g class
  • 与 wpf ComboBox DisplayMemberPath、SelectedValue 和 SelectedValuePath 混淆

    我一直在努力解决这些组合框属性 显示成员路径 选定值 选定的值路径 我正在构建一个主详细信息表单 组合框中充满了客户 用户在组合中选择客户 所有文本框 EG 均正确填写 我遇到的问题是我已经让它工作了 但我不理解这些属性和差异 有没有一个很
  • WPF 中按钮的启用和禁用状态的不同图像

    我想根据按钮的状态更改下面代码中按钮的图像 即使用不同的图像来启用和禁用状态
  • 通过样式设置 DataGridCellsPresenter 的 ItemsPanel 不起作用

    我正在尝试设置ItemsPanel of a DataGridCellsPresenter在我的窗口的资源中 Bu
  • 手动更新目标后,单向绑定停止工作

    我有这样的WPF绑定代码 TestModel source new TestModel TestModel target new TestModel Bind source target BindingMode OneWay source
  • 如何在 C# / .NET 中创建内存泄漏[重复]

    这个问题在这里已经有答案了 可能的重复 托管代码中是否可能存在内存泄漏 特别是 C 3 0 https stackoverflow com questions 6436620 is it possible to have a memory
  • 带有命令绑定的 KeyBinding 不适用于 TextBox UpdateSourceTrigger LostFocus

    我正在使用 MVVM 并遇到以下问题 我的 TextBox Text 与 UpdateSourceTrigger LostFocus 绑定 这就是用户想要的 我有一个带有 SaveCommand CommandBinding 的按钮 这有效
  • 基于另一个组合框的所选项目绑定组合框 - MVVM WPF

    我目前有一个组合框 其中填充了艺术家姓名 一旦选择了艺术家 我需要将其绑定到另一个组合框 在我看来 这些设置如下
  • 是否可以在事件处理程序开始期间和结束期间更改一次视图?

    我只需单击一下即可从数据库获取数据 我有一个事件处理程序 触发时应在状态栏中显示 数据检索 并应在事件处理程序结束之前再次更改为 就绪 但文本只更新一次 即第二次 准备就绪 一般是怎么做的 private void Next Click o
  • 如何禁用列表框上的突出显示但保留选择?

    我无法找到如何不允许我的列表框突出显示所选项目 我知道我没有添加触发器来突出显示该项目
  • 不支持 URI 前缀

    我正在尝试使用以下方法加载和播放波形文件 SoundPlayer simpleSound new SoundPlayer pack application MyAssembly component Sounds 10meters wav s
  • WPF 模式进度窗口

    如果这个问题已经被回答了很多次 我很抱歉 但我似乎找不到适合我的答案 我想创建一个模式窗口 在我的应用程序执行长时间运行的任务时显示各种进度消息 这些任务在单独的线程上运行 我能够在过程的不同阶段更新进度窗口上的文本 跨线程通信一切正常 问
  • WPF 中处理系统关闭

    如何在 WPF 中重写 WndProc 当我的窗口关闭时 我尝试检查我正在使用的文件是否被修改 如果是 我必须提示用户 你想保存更改吗 消息 然后关闭正在使用的文件和窗口 但是 当我的窗口仍然打开时 我无法处理用户重新启动 关闭 注销的情况
  • 获取 TreeView 中子节点的 SelectedIndex

    我目前正在使用 C 开发一个 wpf 项目 我创建了一个树视图 其中包含父节点和子节点 我想知道是否有办法获取用户单击的子节点的索引 类似于使用组合框时的 SelectedIndex 我尝试过各种方法 例如 int val TreeView
  • 如果.Net Core可以在Windows上运行,为什么不能在.Net Framework中引用.Net Core DLL?

    我明白为什么 Net Framework 可能会在 Net Core IE 中导致问题 因为不存在特定于 Windows 平台的 API 但是为什么不能直接引用 Net Core 作为 Net Framework 中的库呢 如果 Net C
  • 通过等待任务或访问其 Exception 属性都没有观察到任务的异常

    这些是我的任务 我应该如何修改它们以防止出现此错误 我检查了其他类似的线程 但我正在使用等待并继续 那么这个错误是怎么发生的呢 通过等待任务或访问其 Exception 属性都没有观察到任务的异常 结果 未观察到的异常被终结器线程重新抛出
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里

随机推荐

  • mariadb声明变量语法错误

    我使用 mariadb 和 heidisql 来执行 sql 声明 AccountID INT 插入帐户 名字 mi 姓氏 电子邮件 is admin is enabled date created 值 testfirstname a te
  • htaccess 强制 https 并将 www 重定向到非 www,但没有其他子域

    我知道有很多类似的线程 但似乎没有一个与我的确切问题相符 这是我正在尝试做的事情 1 http www mydomain com gt https mydomain com 2 http mydomain com gt https mydo
  • PHP 友好 URL 路由帮助

    我正在构建一个通过index php 运行所有代码的网站 例如index php controller something id 01234 我想使用 PHP 创建友好的 URL 所以我这样做 request str replace roo
  • SQL Server 通配符[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions Does Select from t
  • Python:检测黑色方块

    我正在尝试检测黑色方块 到目前为止 这是我的代码 frame cv2 imread squares jpg img cv2 GaussianBlur frame 5 5 0 img cv2 cvtColor frame cv2 COLOR
  • msgrcv - SA_RESTART 标志不起作用

    我的使用 IPC 队列在线程之间通信的代码有问题 我需要安全地处理 SIGINT 让程序在关闭之前出现 SIGINT 时完成所有活动线程 不过 我在寻找解决方案方面遇到了严重的问题 因为即使使用带有标志 SA RESTART 的 SIGIN
  • 更改 RMarkdown pdf 输出中图形标题的字体大小

    我想缩小 R Markdown 文档中所有标题 图形和表格 的字体大小 我用的是bookdown 最终输出是 pdf 我正在 R Studio 中工作 为了加载图片 我使用include graphics函数来自knitr 因为有人告诉我这
  • 无法加载时间字符串的 IOSurface。本地渲染而不是 swift 4

    当我运行我的项目时 你能帮我解决这个问题吗 无法加载时间字符串的 IOSurface 改为本地渲染 我不知道我的编码发生了什么 请帮忙 I fixed the problem Select target gt General gt sele
  • 正则表达式匹配数字和字符

    如何创建仅匹配字符和数字的正则表达式 这个正则表达式匹配宽度数字 D g 如何添加类似字符 等等 仅匹配字母和数字 A Za z0 9 将所需的字符添加到上述字符类中 以匹配该特定字符 A Za z0 9 您可以将上述正则表达式减少为 w
  • 渲染表格中的下标/上标(闪亮)

    我在一个闪亮的应用程序中有一个数据表 我想在其中添加上标到我的观察结果中 这些应该详细说明观察结果是否是估计值 以及观察年份距参考年份有多远 此数据已经在我的数据集中 例如 特定的观察结果可能显示 75 上标 3 e 这可能吗 我今天也有同
  • $sce:itype 尝试信任需要字符串的内容中的非字符串值:上下文:resourceUrl

    我想播放存储在我的 sails 服务器中的歌曲 路径是http localhost 4000 images 123 mp3 在前端 我使用 ng repeat 列出来自服务器的歌曲 div div i class fa fa play ci
  • helm 图表中的动态命名空间变量

    我与四个团队合作 他们使用在 kubernetes 命名空间中设置的完全相同的环境 我创建了 helm 图表来安装这些环境 一切正常 但由于主机名格式如下 我必须手动创建入口
  • ClickOnce 快捷方式无法启动应用程序

    我在 VS 2017 中创建了一个使用 ClickOnce 安装的 WPF 应用程序 将解决方案部署到网络位置后 我可以通过访问 application 链接在我的 64 位 Windows 10 计算机上安装 但是 该应用程序安装后无法在
  • 完成时更新整个

    编辑单元格后 我很难重新渲染 PrimeFaces 数据表 更改一个单元格中的值可能会更改其他单元格中的条目 因此需要刷新整个表格 这是 JSF 页面
  • 如何与 Kivy GUI 一起运行 Tornado 事件循环?

    我的客户端应用程序使用KivyGUI Kivy 有自己的事件循环 并使用 WebSocket 协议连接到服务器Tornado Tornado 也有一个事件循环 这就是连接部分是异步的原因 我希望用户在 Tornado 客户端运行监听服务器消
  • 如何删除 NSMutableArray 中具有相同属性值但只有一个的所有对象

    我有一个带有 url 字符串属性和标题的历史对象 我想搜索 URL 包含搜索字符串的对象的所有历史记录 然后删除所有重复项 例子 我有一系列历史对象 其中 20 个都是 https www google com https www goog
  • C# Winforms 复选框不指示焦点

    如果复选框是 Tab 键顺序 0 中的第一个控件 则在显示表单时并不表示它具有焦点 事实上 它确实具有焦点 您可以通过按空格键来选中 取消选中控件来演示这一点 如果您先按 Tab 键 然后按 Shift Tab 键返回到该复选框 则标签会出
  • 闪亮滑块输入从最大到最小

    是否可以制作一个以降序显示值的 sliderInput 从左到右 例如 5 4 3 2 1 runApp list ui fluidPage sliderInput test min 5 max 1 value 3 step 1 serve
  • 在Java中将BufferedImage转换为Mat(OpenCV)[重复]

    这个问题在这里已经有答案了 我试过这个link https stackoverflow com questions 14958643 converting bufferedimage to mat in opencv并有下面的代码 我的程序
  • WPF 窗口不会释放其资源,直到程序终止

    我一直在阅读有关 WPF 内存处理的内容 并跟踪了前 5 个和前 8 个内存泄漏陷阱 但在我目前的情况下没有任何帮助 我的软件有一个问题 WPF 在程序终止之前不会释放内存 如果我永远让它消失 无论我做什么都会导致 OutOfMemoryE