如果没有保存引用,SystemTimers.Timer 何时被视为垃圾?
Posted
技术标签:
【中文标题】如果没有保存引用,SystemTimers.Timer 何时被视为垃圾?【英文标题】:When is SystemTimers.Timer considered garbageif no reference is saved? 【发布时间】:2020-06-12 11:05:48 【问题描述】:我很想知道 System.Timers.Timer 何时被视为垃圾并因此被垃圾收集器收集,如果我不存储对它的引用,但它已启用。 但是在什么时候我的计时器被认为是垃圾?
考虑以下代码:
public void TriggerUpdateStatus()
toolStripStatusLabel1.Text = "*";
new Timer()
Interval = 1000,
Enabled = true
.Elapsed += new ElapsedEventHandler(
(object sender, ElapsedEventArgs args) =>
toolStripStatusLabel1.Text = "";
Timer t = ((System.Timers.Timer) sender);
t.Stop();
t.Dispose();//Is this needed?
);
当我的代码触发更新时,此代码块将每两秒运行一次,然后在我的表单的底角添加一个星号,表示连接有效且良好。我创建了一个没有引用的计时器,它会在一秒钟后再次移除星星,自行停止并自行处理。
【问题讨论】:
它在运行时如何/为什么会被视为垃圾??? 在第 10 行,它会自行停止,并在第 11 行自行处理。 您问:如果我不存储对它的引用,但它已启用。现在是哪个? 您的Timer
对象甚至在方法返回之前(根据您的代码)就有资格进行垃圾回收。但是,您无法确切知道何时收集此对象。 .NET 中的 GC 以这种方式是不确定的。请注意,Timer
是一个 Component
,它有一个终结器,如果它将在收集时运行(更准确地说,处理终结器队列的时间),它将自动禁用正在运行的计时器。
【参考方案1】:
不,t.Dispose()
,没有必要,无论如何都会被收集。
这个问题本身似乎传达了一个关于 GC 和 Dispose
如何工作的深刻误解(我强调了这个词 似乎)。 GC 完全不知道Dispose
做了什么,也不在乎。一个对象是否被处理并不会影响该特定对象是否适合收集;这是两个完全正交的概念。
Dispose 是一种释放非托管资源的机制,它与垃圾收集器的工作方式无关。
如果这很清楚,那么Dispose
尽管有礼貌,但甚至不是绝对必要的; Dispose
(或其所需部分)将在最终收集计时器时运行(该对象无法访问且寿命短,因此不应花费太长时间),放入终结器队列并在某个未确定的未来完成;有礼貌并建议 dispose 以便确定性地释放与对象关联的所有非托管资源,而不是依赖于终结器队列决定运行时,这带来了下一点:
为什么你每两秒更新一个Timer
然后立即处理它?拥有一个计时器并每次都重置它不是更容易吗?
【讨论】:
所以如果我没看错你说的话,一旦计时器停止,它就会被收集,或者我可以遇到在计时器停止之前收集它的时间吗?为了回答您的问题,我知道这是解决问题的一种令人发指的方法,我尝试了一些方法,但总是遇到两个计时器不同步或一个计时器完全停止工作的问题。以上是关于如果没有保存引用,SystemTimers.Timer 何时被视为垃圾?的主要内容,如果未能解决你的问题,请参考以下文章
c#传递引用对象作为参数的时候就没有必要用ref关键字,对吗