【问题标题】:C# WinForm Memory LeakC# WinForm 内存泄漏
【发布时间】:2012-07-08 14:07:11
【问题描述】:

我有一个大的 winform 类,它从一个像这样的小人那里调用:

    void login()
    {           
        mainForm f1 = new mainForm();                
        f1.ShowDialog();
    }

mainForm 登录后会占用大量内存(我在任务管理器中查看)。关闭主窗体后,程序返回登录窗体。在这一步我再次检查任务管理器,发现我的程序没有释放 mainForm 使用的内存。登录后,我的程序崩溃并显示“内存不足”错误。

我不得不说我测试了 f1.Dispose()、f1=null、GC.Collect() 和我发现的所有其他方法。

它只会在我关闭登录表单时释放内存(它是Application.Run中使用的起始类)

我想销毁mainForm实例(f1)和这个表单的所有资源,就像我关闭程序时一样。

【问题讨论】:

  • 你说你已经添加了f1.Dispose(); f1 = null; GC.Collect(); 之后 f1.ShowDialog();,它没有工作?另外,它是在调试还是发布?
  • 静态事件处理程序的味道
  • 是的,我检查了我在不同论坛上找到的所有方法。什么也没发生。

标签: c# memory memory-leaks


【解决方案1】:

不太确定 OOM 是否与登录表单有关。正如Taskmgr.exe 所报告的那样,关闭或处理表单会减少内存使用量肯定不是这种情况。

但你肯定做错了。对话框在 Winforms 中的处理方式不同,它不会像使用 Show() 显示的表单那样自动处理。因此,您希望在对话框关闭后检索用户在对话框中输入的任何内容,这在对话框被释放时将是危险的。所以你必须自己做。正确的模式是:

    using (mainForm f1 = new mainForm()) {
        if (f1.ShowDialog() == DialogResult.Ok) {
            // Retrieve data entered by user and do something with it
            //...
        }
    }

使用 using 语句确保对话框实例在您检索到对话框结果后被释放。

【讨论】:

  • using 语句对我没有帮助。你的代码正是我所做的。
  • 这就是我在第一句话中告诉你的。您根本没有记录有关 OOM 状况的任何内容。我只能假设您的代码在其他地方也与您的 sn-p 相似,这当然是触发 OOM 条件的一种方式。如果您不知道泄漏的位置,请使用内存分析器。
【解决方案2】:

几个想法:

【讨论】:

  • 我之前检查过 using 语句,但没有帮助。关于其他控件,我只是使用了 .Net 标准控件和我自己的控件,我应该说我也有一些非托管代码。奇怪的是,当我关闭 mainForm 时,我看不到程序的内存使用有任何变化。我认为至少它应该释放一部分内存。关于windbg和sos,不,我会检查它们。
  • 谢谢,我使用了内存分析器,发现了一些问题。我认为发现所有问题需要一些时间。
【解决方案3】:

也许主窗体在显示时会创建对自身的引用,检查它分配的任何引用/委托/事件并确保它们在主窗体完成时未注册,或者将事件处理程序(即应用程序事件)移动到单独的类。

到目前为止,100% 的时间我都“发现了 .NET 内存泄漏”,但事实并非如此!处理所有一次性用品,注意你如何处理包含引用的静态数据,不要进行重复的事件订阅,并在可能的情况下整理它们。

使用 SOS,正如 mouters 所说,在运行 dispose 并调用 GC.Collect(3) 几次后检查 mainform 类上的 gcroots,一旦你跟踪引用的位置,你应该会发现错误。

【讨论】:

    猜你喜欢
    • 2016-01-27
    • 2010-11-11
    • 2017-02-18
    • 1970-01-01
    • 2015-11-19
    • 2014-11-01
    • 2020-03-31
    • 2016-03-15
    • 2015-07-25
    相关资源
    最近更新 更多