[英]C# Timers and Garbage Collection
根據MSDN ,應該保留對System.Threading.Timer的引用,否則它將被垃圾收集。 因此,如果我運行此代碼,它不會寫任何消息(這是預期的行為):
static void Main(string[] args)
{
RunTimer();
GC.Collect();
Console.ReadKey();
}
public static void RunTimer()
{
new Timer(s => Console.WriteLine("Hello"), null, TimeSpan.FromSeconds(1), TimeSpan.Zero);
}
但是,如果我通過將計時器存儲在臨時局部變量中來稍微修改代碼,它會幸存並寫入消息:
public static void RunTimer()
{
var timer = new Timer(s => Console.WriteLine("Hello"));
timer.Change(TimeSpan.FromSeconds(1), TimeSpan.Zero);
}
在垃圾收集期間,顯然無法從根或靜態對象訪問計時器。 所以你能解釋為什么計時器存活下來嗎? 保留的參考在哪里?
每個Timer
引用一個TimerHolder
,它引用一個TimerQueueTimer
。 該實現通過調用TimerQueueTimer
UpdateTimer()
保持對TimerQueueTimer
的內部引用。
在正常情況下,您的計時器可以自由收集, 最終確定TimerHolder
並從內部隊列中刪除TimerQueueTimer
。 但是簡單的構造函數Timer(TimerCallback)
TimerSetup()
以Timer
本身作為狀態調用TimerSetup()
。 因此在這種特殊情況下, TimerQueueTimer
的狀態會引用回Timer
,從而阻止它被收集。
效果與保持臨時局部變量無關。 由於Timer
機制的內部原因,它恰好正常工作。 按照MSDN的建議,保持對計時器的引用更清晰,更安全。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.