C# 线程。计时器阻止GC收集
我有一个内存泄漏问题,我想知道是否有人能告诉我我做错了什么(或者我错过了什么Microsoft bug)。下面是一个示例应用程序,演示了该问题。调用TestCollectTimer.Test()运行示例 问题是,无论创建了多少“MyTimerData”,或者调用了多少次GC.Collect(),MyTimerData的终结器在应用程序关闭之前都不会被调用C# 线程。计时器阻止GC收集,c#,C#,我有一个内存泄漏问题,我想知道是否有人能告诉我我做错了什么(或者我错过了什么Microsoft bug)。下面是一个示例应用程序,演示了该问题。调用TestCollectTimer.Test()运行示例 问题是,无论创建了多少“MyTimerData”,或者调用了多少次GC.Collect(),MyTimerData的终结器在应用程序关闭之前都不会被调用 class TestCollectTimer { public static void Test() { f
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) { }
}
类TestCollectTimer
{
公共静态无效测试()
{
对于(int index_A=0;index_A<100000;index_A++)
{
MyTimerData mtd=新MyTimerData();
mtd=null;
}
GC.Collect();
《睡眠》(2000年);
GC.Collect();
表格f=新表格();
f、 ShowDialog();
}
}
类MyTimerData
{
公共系统.Threading.Timer m_Timer;
公共MyTimerData()
{
this.m_timer=new System.Threading.timer(
新系统.Threading.TimerCallback(this.TimerCall),
无效的
System.Threading.Timeout.Infinite,
系统、线程、超时、无限);
}
~MyTimerData()
{
Show(“收集我的计时器数据”);
}
公共无效TimerCall(对象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);
}
}
类TestCollectTimer
{
公共静态无效测试()
{
对于(int index_A=0;index_A<100000;index_A++)
{
使用(MyTimerData mtd=new MyTimerData())
{
//在这里做你的事
}
}
GC.Collect();
表格f=新表格();
f、 ShowDialog();
}
}
类MyTimerData:IDisposable
{
公共系统.Threading.Timer m_Timer;
公共MyTimerData()
{
this.m_timer=new System.Threading.timer(
新系统.Threading.TimerCallback(this.TimerCall),
无效的
System.Threading.Timeout.Infinite,
系统、线程、超时、无限);
}
公共无效TimerCall(对象o){}
公共空间处置()
{
处置(真实);
}
受保护的无效处置(bool处置)
{
m_timer.Dispose();
总干事(本);
}
}
您可以查看规则CA1001:在发布模式下运行它,而不附加调试程序。看,我想这是因为你启动了计时器,但没有停止。运行计时器可以让自己保持活力,这样他们就不会被垃圾收集(因为这比你的计时器无法预知地死去要好)。我不确定通过传递Timeout.Infinite这两个参数来完成什么任务。不过,你说的是“创建一个永远不会启动的计时器”。@joewite这与:“只要使用计时器,就必须保留对它的引用。与任何托管对象一样,当没有对计时器的引用时,计时器将接受垃圾收集。计时器仍处于活动状态这一事实并不妨碍对其进行收集。”