【问题标题】:WPF : is it cause a memory leak?WPF:它会导致内存泄漏吗?
【发布时间】:2011-08-11 12:36:25
【问题描述】:

[编辑]

在静态类 myWork 中,

public static class myWork()
{
    public static SomeWPFCollectionType myGenerate()
    {
        SomeWPFCollectionType myGenerated=new SomeWPFType();
        List<SomeType> myLists=new List<SomeWPFType>();

        for(int i=0 ; i < someCount ; i++)
        {
            myLists.Add(new SomeType(...););
        }

        myGenerated = SomeTypeToSomeWPFCollection(myGenerated);
        return myGenerated;
    }
}

....

public partial class MainWindow : Window
{

    ...

    private void btn1_Click(...)
    {
        this.someControl.someCollection = myWork.myGenerate();
    }

}
  1. 什么时候清除 myLists 的内存?
  2. 什么时候清除 myGenerated 的内存?

当我第一次调用 btn1_click 时,我预计会这样做。 但 Windows 的任务管理器报告似乎存在内存泄漏,很明显。

-编辑-

我认为我的代码没有在 myLists 上发生泄漏。因为,

        ....

        myGenerated.Unloaded += delegate(...)
        {
             //i breaked here and see a value of myList in the Watch window of VS.
             Debug.write(myList.ToString());      
        }

        myGenerated = SomeTypeToSomeWPFCollection(myGenerated);
        return myGenerated;

        ....

当 myGenerated 被卸载,但 myList 仍有 15 个项目。

【问题讨论】:

  • 你不能处理myLists - 它是一个List&lt;T&gt;,它没有实现IDisposable。此外,您提供的代码中存在各种错误。不能编译的代码不能泄露。如果您可以提供一些真实代码,我们可以提供更多关于是否存在泄漏的信息。
  • 你的问题不清楚。每次按下按钮时,您都会创建一个新集合,这看起来不像通常会做的事情,因为 Jon Skeet 要求发布可以编译的代码,我们可以从那里开始。
  • 物品会被GC几乎任意收集,你点击了多少次按钮? someCount 有多大,SomeWPFType 是“大”,是一次性的吗?
  • 我已编辑。我认为我的真实代码不是重点。我正在学习 C#,所以我需要一般信息。对不起,谢谢。
  • 人们必须开始解释他们为什么投反对票

标签: c# memory memory-leaks


【解决方案1】:

垃圾收集器负责释放未使用的先前分配的内存。

【讨论】:

    【解决方案2】:

    } 1.myLists 什么时候清除内存?

    当您单击按钮时。这显然不会清除之前的 myGenerated 实例。

    2.myGenerated 的内存清除时间是什么时候?

    每次单击按钮时,您的代码都会创建一个新的 myGenerated 实例。

    【讨论】:

      【解决方案3】:

      一旦 myLists 和 myGenerated 变量超出范围,垃圾收集器会随时释放内存。

      myLists 的范围仅在您的静态类中,而 myGenerated 的范围要大得多。

      此外,当单击按钮时,myGenerated 的新实例将替换旧实例。这使得旧实例可以免费进行垃圾回收。

      因此,您提供的代码中没有真正的内存泄漏。

      我不确定这是否能回答您的问题,但希望对您有所帮助。

      【讨论】:

      • 如果您对一般编程很陌生,scope rules 可能有助于理解 C# 中的范围。 C# 中的垃圾收集器很酷,因为它会自动管理内存的释放,所以大多数时候你不必担心它;有关更多详细信息,请参阅link。话虽如此,如果“SomeWPFCollectionType”实现了 IDisposable,您可以使用“.Dispose”方法显式释放/释放内存。希望这会有所帮助!
      • @mjk6026 在您最近的更新中,您在“myGenerate”方法中添加了一个“Debug.write”,对吗?由于在此方法中定义了“myList(s)”,并且您没有离开该方法的范围,因此“myList”仍然存在。如果您将“Debug.write”放在“btn1_click(...)”的末尾,我想“myList(s)”将不存在。 (实际上,它甚至不会编译)希望这会有所帮助,我不确定,因为我不知道您要解决的“大局”问题(即:试图找到内存泄漏,你怎么知道你有内存泄漏等等)
      【解决方案4】:

      我没有在您发布的代码中看到内存泄漏。任务管理器不是检查内存泄漏的正确工具。 垃圾收集器不需要立即释放所有未引用的对象。

      如果您确实怀疑内存泄漏,请查看 sos.dll 进行调试。 见:http://www.codeproject.com/KB/dotnet/Memory_Leak_Detection.aspx

      在第二个代码片段中,委托捕获对新创建和填充的列表的引用,当然会将这个列表转储到调试窗口。

      简而言之:代码可能没问题,但您必须提高调试技能。

      【讨论】:

        【解决方案5】:

        如果是静态列表,则只生成一次。如果这是动态的,那么这不是正确的解决方案。如果您的目标是将控件绑定到动态内容,则将集合公开为 ObservableCollection 属性并绑定到它。在您的“内存泄漏”上,直到 myGenerate() 生成的 SomeWPFCollectionType 超出范围,它不会被垃圾收集。如果将控件绑定到新集合,则旧集合似乎应该被垃圾收集。我认为您的代码有缺陷,但我没有看到“内存泄漏”。

                private List<DocFieldEnum1row> docFieldEnum1rows;
        
                public List<DocFieldEnum1row> DocFieldEnum1rows 
                { 
                    get 
                    {
                        if (docFieldEnum1rows == null)
                        {
                            docFieldEnum1rows = new List<DocFieldEnum1row>();
                            // code to populate list here                
                        }
                        return docFieldEnum1rows;
                    } 
                }
        

        【讨论】:

          猜你喜欢
          • 2011-06-16
          • 2021-03-23
          • 2021-09-25
          • 2014-12-08
          • 1970-01-01
          • 1970-01-01
          • 2010-09-09
          • 2011-10-28
          相关资源
          最近更新 更多