簡體   English   中英

C#定時器和垃圾收集

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM