小内存泄漏

本文关键字:泄漏 内存 | 更新日期: 2023-09-27 18:06:04

线程、委托和垃圾收集新功能

我在Visual Studio 2013中有一个c#程序,该程序在后台线程上运行循环,以不断更新主线程中窗体上的控件。当循环运行时(并且仅当循环运行时),性能监视器显示该程序的私有字节有一个小而稳定的增长。

当后台线程停止并加入时,私有字节的使用没有减少,但它不再增加。这个程序需要在循环线程中运行很长时间,所以一个小的泄漏可能在几个小时或几天后成为一个问题。

我可以注释掉循环中调用update方法的行;这成功地遏制了这个问题。我在做什么来防止该方法中的垃圾收集?

注:如果你给我指一个程序来查找堆,请一步一步地告诉我如何安装和使用它。我最近有点筋疲力尽,到目前为止我在网上看到的东西对我的大脑来说还不够明显。

    private IAsyncResult iar;  // Store the IAsyncResult to check for completion the next time I call it.
    public delegate void Assisted_UpdateTimer(int totalSeconds, int secondsElapsed, int secondsRemaining);
    public void UpdateTimer(int totalSeconds, int secondsElapsed, int secondsRemaining)
    {
        if (this.InvokeRequired || pbTimeBar.InvokeRequired)  // If we need to be threadsafe
        {
            if (iar != null)  // If we've invoked something before
            {
                if (iar.IsCompleted)  // If the last thing we invoked has completed
                {
                    this.EndInvoke(iar);
                    Assisted_UpdateTimer _delegate = new Assisted_UpdateTimer(UpdateTimer);
                    iar = this.BeginInvoke(_delegate, totalSeconds, secondsElapsed, secondsRemaining);
                }
            }
            else  // Invoke for the first time
            {
                Assisted_UpdateTimer _delegate = new Assisted_UpdateTimer(UpdateTimer);
                iar = this.BeginInvoke(_delegate, totalSeconds, secondsElapsed, secondsRemaining);
            }
        }
        else  // The actual method code
        {
            TimeSpan timeElapsed = new TimeSpan(0, 0, secondsElapsed);
            TimeSpan timeRemaining = new TimeSpan(0, 0, secondsRemaining);
            int percent = (int)(((double)secondsElapsed / (double)totalSeconds) * 100);
            if (pbTimeBar.Maximum != totalSeconds) pbTimeBar.Maximum = totalSeconds;
            if (secondsElapsed >= 0) pbTimeBar.Value = secondsElapsed;  // pbTimeBar is a progress bar
            // Add text to progress bar
            pbTimeBar.CreateGraphics().DrawString(percent + "%", new Font("Arial", (float)8.25, FontStyle.Regular), new SolidBrush(Color.FromArgb(255, 0, 0, 0)), new PointF(pbTimeBar.Width / 2 - 10, pbTimeBar.Height / 2 - 7));
            labElapsed.Text = string.Format("{0:00}:{1:00}:{2:00} Elapsed", timeElapsed.Hours, timeElapsed.Minutes, timeElapsed.Seconds);
            labRemaining.Text = string.Format("Remaining {0:00}:{1:00}:{2:00}", timeRemaining.Hours, timeRemaining.Minutes, timeRemaining.Seconds);
            trayIcon.Text = string.Format("Toast Timer'nRemaining: {0:00}:{1:00}:{2:00}'nElapsed: {3}%", timeRemaining.Hours, timeRemaining.Minutes, timeRemaining.Seconds, percent);
        }
    }

小内存泄漏

我还没有检查您的完整代码,但内存泄漏可能是强委托引用的可能输出。您可以看到,当您将委托附加到对象的事件时,除非手动删除委托引用,否则该对象永远不会被垃圾收集。以下是来自msdn的文档参考,可以帮助您更好地理解场景和可能的解决方案-

http://msdn.microsoft.com/en-us/library/aa970850 (v = vs.110) . aspx

监听事件可能导致内存泄漏。监听事件的典型技术是使用特定于语言的语法,将处理程序附加到源上的事件。例如,在c#中,该语法是:source。SomeEvent += new SomeEventHandler(MyEventHandler).

对于你问题的最后一部分-我通常使用Ant Profiler进行内存测试。它不是免费的,但试用版通常可以工作,并给你足够的时间来解决问题。

http://www.red-gate.com/products/dotnet-development/ants-performance-profiler/

http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/

注释:我猜重复调用UpdateTimer可能会导致内存泄漏,如果它在每次调用中附加新的委托。