线程.计时器阻止GC收集
本文关键字:GC 收集 计时器 线程 | 更新日期: 2023-09-27 18:13:54
我有内存泄漏问题,我想知道是否有人能告诉我我做错了什么(或者我错过了什么微软bug)。下面是演示该问题的示例应用程序。调用TestCollectTimer.Test()来运行示例。
问题是,不管创建了多少个"MyTimerData",或者调用了多少次GC.Collect(),直到应用程序关闭,MyTimerData的终结器才会被调用。
class TestCollectTimer
{
public static void Test()
{
for (int index_A = 0; index_A < 100000; index_A++)
{
MyTimerData mtd = new MyTimerData();
mtd = null;
}
GC.Collect();
Thread.Sleep(2000);
GC.Collect();
Form f = new Form();
f.ShowDialog();
}
}
class MyTimerData
{
public System.Threading.Timer m_timer;
public MyTimerData()
{
this.m_timer = new System.Threading.Timer(
new System.Threading.TimerCallback(this.TimerCall),
null,
System.Threading.Timeout.Infinite,
System.Threading.Timeout.Infinite);
}
~MyTimerData()
{
MessageBox.Show("Collect My Timer Data");
}
public void TimerCall(object o) { }
}
谢谢你的帮助
在调试模式下,所有局部变量的作用域都被人为地扩展到它们的封闭方法的末尾,因此在调试器中检查完它们之前它们不会被收集。
您的代码在发布模式下编译并在没有附加调试器的情况下运行时按预期工作。
您还可以将for循环移动到它自己的方法中,这样即使在调试模式下,也可以在它返回后收集计时器。
如何处理定时器?
class TestCollectTimer
{
public static void Test()
{
for (int index_A = 0; index_A < 100000; index_A++)
{
using(MyTimerData mtd = new MyTimerData())
{
//do your stuff here
}
}
GC.Collect();
Form f = new Form();
f.ShowDialog();
}
}
class MyTimerData : IDisposable
{
public System.Threading.Timer m_timer;
public MyTimerData()
{
this.m_timer = new System.Threading.Timer(
new System.Threading.TimerCallback(this.TimerCall),
null,
System.Threading.Timeout.Infinite,
System.Threading.Timeout.Infinite);
}
public void TimerCall(object o) { }
public void Dispose()
{
Dispose(true);
}
protected void Dispose(bool disposing)
{
m_timer.Dispose();
GC.SuppressFinalize(this);
}
}
您可以查看规则CA1001: http://msdn.microsoft.com/en-us/library/ms182172.aspx