【问题标题】:How to reduce memory usage of a windows form application in C# VS 2010 Professional如何在 C# VS 2010 Professional 中减少 Windows 窗体应用程序的内存使用量
【发布时间】:2011-03-10 19:38:21
【问题描述】:

我有一个带有简单 gui 的应用程序,图形很少,但对象很多,即。标签文本框和一些面板。
在某些面板上,它运行 LDAP 查询,在其他面板上,它查询正在运行的进程并检查 NIC 状态。
当我进入 LDAP 搜索器面板时,内存使用量下降到应用程序 30mb,当我返回只运行计时器的主面板时,它跳到大约 300mb + 然后不断累积,我运行 GC.Collect() 的频率为我可以在运行主要方法之后最小化并且仍然没有效果,我在项目属性的构建下使用了优化代码,并且我剥离了所有的 Using system.whatever。我是一个相当新的程序员,距离我开始做 Windows 窗体只有大约 6 个月的时间。你能帮忙的话,我会很高兴。我的应用程序本质上是一个 GUI,它在后台运行一个计时器,然后执行上述查询和一些任务技能。没有什么太占用内存了。 gui 对象本身会不会占用我的内存?

    public MainMethod()
    {
        try
        {

            InitializeComponent();

            notifyIcon1.Visible = true;


            // this.Opacity = .5;
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            aTimer.Interval = 1000 * 10;

            pword();
            this.ShowInTaskbar = false;
            this.Hide();
            this.Visible = false;
           // GC.Collect();
        }
        catch (Exception ex)
        {
            eventWriter(ex);
        }

    }
    public void pword()
    {
        try
        {

            bool nCheck;
            string[] infoArray = new string[4];
            nCheck = checker.checkNetwork();
            int dayNum = 0;

            if (nCheck == true)
            {

                infoArray = checker.checkAD();   //this is similar code to CheckNetwork except it returns values from the user's AD account properties.
                label3.Text = infoArray[0];
                label2.Text = infoArray[2];
                label1.Text = infoArray[3];
                label21.Text = infoArray[0];
                label22.Text = infoArray[1];
                label23.Text = infoArray[2];
                label24.Text = infoArray[3];
                days = infoArray[3];
                dayNum = int.Parse(days);
                if (dayNum <= 15)
                {
                    timedIntervalChanger(2);
                    aTimer.Start();
                    GC.Collect();
                }
            }
            else
            {
                timedIntervalChanger(1);
                aTimer.Start();
                GC.Collect();
            }
        }
        catch (Exception ex)
        {
            eventWriter(ex);
        }

} 公共布尔检查网络() { 布尔连接; 尝试 {

            String objectName = WindowsIdentity.GetCurrent().Name;


            if (objectName.Contains("administrator"))
            {
                connected = false;
                return connected;
            }

            else
            {





                // Sets domain
                string LdapDomain = "mydomain.com"
                //Sets properties for directory Entry and Searcher
                string connectionPrefix = "LDAP://" + LdapDomain;
                DirectoryEntry entry = new DirectoryEntry(connectionPrefix);
                DirectorySearcher mySearcher = new DirectorySearcher(entry);


                mySearcher.Filter = "(&(objectClass=user)(objectCategory=Person)(|(cn=" + objectName + ")(sAMAccountName=" + objectName + ")))";

                //instantiates result object from the search

                SearchResult LDAPresult = mySearcher.FindOne();

                entry = LDAPresult.GetDirectoryEntry();
                connected = true;

            }
            return connected;
        }
        catch
        {
            connected = false;
            return connected;
        }
    }
    public void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        try
        {

            notifyIcon1.Visible = true;
            notifyIcon1.ShowBalloonTip(1000 * 9, "Test", "test text", ToolTipIcon.Warning);


         pword();
        }
        catch (Exception ex)
        {
            eventWriter(ex);
        }


    }

当我显示表单时,内存使用量急剧增加。每个方法都是独立的,我省略了一些对象实例化代码。

【问题讨论】:

  • 您观察到什么问题?
  • 正如@mjmarsh 所说,如果您可以向我们展示您的一些源代码,我们可以为您提供更多帮助。 (但是,他的建议很好。)
  • 只是总体上使用了太多内存,它并没有真正影响机器,但我希望一个小型应用程序不使用 300mb 的内存。
  • 您知道通常的建议是避免使用 GC.Collect,因为它会降低性能,对吧?它迫使对象进入更高的世代,并导致每个集合花费更长的时间。如果您真的知道自己在做什么,请使用它,但不要只是在您的代码中使用它。
  • 计时器做了什么分配?循环(或计时器)中发生的事情是你应该看的,就像这里所说的那样,请发布一些代码?您还如何测量内存消耗?你能给出所有堆计数器和私有字节计数器中的字节数吗? (所以我们知道要寻找什么样的内存)。

标签: c# winforms visual-studio-2010 memory-management


【解决方案1】:

我们真的需要更多信息。但有几点建议:

  1. 对所有一次性对象使用 using 关键字或调用 Dispose()
  2. 确保在侦听完事件后取消注册事件处理程序

我不确定您使用的是什么 LDAP 库,但在 System.DirectoryServices 中,许多类(如 DirectoryEntry)实现了 IDisposable,如果不处理它们可能会“泄漏”

【讨论】:

  • 我正在使用 System.DirectoryServices 和目录条目 directorysearcher,本质上是我在 LDAP 中查询特定用户帐户并返回各种用户对象属性。内存使用在我实例化这些对象之前就开始了。
  • 我会通过调用 dispose 处理任何未使用的对象,我感觉 GC.Collect 没有拾取它们。
  • 您还需要什么其他信息,我将提供所需的任何信息。
  • 我使用了一个 try catch finally 块,并处理了 finally 块中的对象,并且我的内存使用量没有超过 19mb。
  • @theJerm - 你必须做两件事。保留一个保存您的委托引用的变量,然后在事件上使用“-=”符号。例如:pastebin.com/7UpiNKjM
【解决方案2】:

使用“分析”菜单中的“性能向导”的 .NET 内存分配选项创建一个性能会话,这将帮助您确定需要对代码进行哪些更改以减少内存使用量。

【讨论】:

    最近更新 更多