如何在回调执行之前阻止我的GC收集?

时间:2009-03-04 12:52:08

标签: c#

我需要创建一堆定时器作为局部变量来执行以下操作:

void Foo()
{
    Timer t = new Timer(myTimerCallback,null,1000,Timeout.Infinite);
}

不幸的是,其中一些是由GC收集的,然后在1秒后调用myTimerCallback。由于我有很多计时器,因此无法将它们存储在私有静态成员中。并且很难找到放置GC.Keeplive(t)的地方。

我怎样才能让每个计时器在临终前做好自己的事情?

6 个答案:

答案 0 :(得分:2)

您最好的选择是将它们存储在成员变量中,然后在不再需要它们时将其丢弃。

答案 1 :(得分:1)

将它们存储在成员中,例如List<Timer>

答案 2 :(得分:1)

为什么无法存储它们?也许你可以在他们的工作完成后从那个系列中删除它们?

答案 3 :(得分:1)

重要的是要看到GC.KeepAlive()无法解决您的问题。这只会将对象的生命周期延长到语句。只要计时器需要保持活动,你就必须循环或阻塞。还要注意,Debug构建中局部变量中引用的生命周期是不同的。 JIT让它们保持生命直到方法结束,以允许手表工作。制作棘手的“在调试中工作,在发布模式下不起作用”的问题。

您必须保留对计时器对象的生命引用。这通常是通过类中的字段完成的。生命周期要求现在传递给类对象,只要需要计时器,它就需要保持活动状态。通常不是问题。如果是,则必须使参考静态。

答案 4 :(得分:1)

您可以将它们存储在集合中以保留引用,并在事件方法中从集合中删除引用。我认为您需要使用state参数来标识集合中的计时器(将对定时器的引用或集合中的键作为“new timer”语句中的状态参数传递)。

请注意,回调函数在其他线程上执行,因此您可能/可能同时运行多个回调函数。使用锁定确保安全地完成添加/删除引用。

答案 5 :(得分:0)

A。 System.Threading与System.Timers

值得指出的是,保留引用问题特定于System.Threading.Timer而非System.Timers.Timer


B。 Threading.Timer的Timer(TimerCallback回调)构造函数

这不是解决您的问题的方法,但我认为它仍然与主题相关。

System.Threading.Timer的{​​{1}}构造函数(不使用Timer(TimerCallback callback)的构造函数)对dueTime使用this,这意味着计时器将保留对自身的引用,这意味着它将在垃圾回收中幸免。

state

示例

计时器'C'是使用public Timer(TimerCallback callback) { (...) TimerSetup(callback, this, (UInt32)dueTime, (UInt32)period, ref stackMark); } 创建的,并且一直沿用Timer(TimerCallback callback)

输出

GC.Collect()

代码

A
B
C
A
B
C
GC Collected
B
C
C
B
B
C