小内存泄漏
本文关键字:泄漏 内存 | 更新日期: 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
可能会导致内存泄漏,如果它在每次调用中附加新的委托。