2013-09-23 255 views
3

我的System.Threading.Timer(它有一個回調)永遠不會可靠地觸發。這是我的編程任務的一部分,我輸入計時器應該從文本框運行的時間量。System.Threading.Timer回調永遠不會被調用

定時器聲明如下:

System.Threading.Timer timer = new System.Threading.Timer(WorkerObject.callback, null, delay, Timeout.Infinite); 

和延遲是一個簡單的描述int爲回調火在第一時間延遲(它應該只是一個觸發一次)。

回調方法是這樣的:

public static void callback(Object stateinfo) 
{ 
    stop = true; 
} 

而且,它設置一個標誌,真該停止的循環(正在由一個線程池線程上運行,實際上所有,停止線)。

循環是這樣的:

while (!stop) 
{ 
    currentTextbox.Invoke(new Action(delegate() 
    { 
     currentTextbox.AppendText((counter++) + Environment.NewLine); 
     currentTextbox.Update(); 
    })); 
} 

我的問題是,stop變量始終是超過5000毫秒的任何延遲假的。有沒有辦法「強制」回調始終開火?

+0

這個問題可能不適用(我忘記了API)...但是你啓動計時器嗎? – Jaxidian

+0

該程序只是打印出一個計數器,它不斷遞增,直到計時器停止。 System.Threading.Timer不需要啓動;它延遲後自動啓動(0爲無延遲,但在我的情況下,我指定了延遲) – docaholic

+0

@Jaxidian:'System.Threading.Timer'在您創建時啓動。 –

回答

9

您需要保持對定時器的引用。

最有可能的是定時器對象被垃圾收集,它將運行它的終結器,停止定時器。

只要您需要計時器存活,請堅持參考。

+0

+1。這是一個陰險的問題。如果您在調試器中運行代碼(在調試或發佈模式下),則不會收集定時器。但是如果你在沒有附加調試器的情況下運行它,定時器將被收集。讓我瘋狂*第一次遇到那個。 –

+1

@JimMischel:我完全同意。我難忘的時刻是將委託傳遞給非託管API。調試器連接一切正常,但沒有調試器GC得到了更多的積極性。我想我們都有我們的故事:) –

+0

是的,這就是它! @JimMischel,我有同樣的問題,在調試器中,計時器會正常工作,但否則計時器會被垃圾收集。 – docaholic

1

運行時抖動可能將您的while(!stop)條件優化爲while(true)。 將stop變量標記爲volatile。

private volatile bool stop = false; 
+0

可能會工作,但當有其他選項時,我不會建議'volatile'。 –

4

我會建議使用CancellationTokenSource

static CancellationTokenSource Cancel = new CancellationTokenSource(); 

public static void Callback(object state) 
{ 
    Cancel.Cancel(); 
} 

和你的循環:

while (!Cancel.IsCancellationRequested) 
{ 
    ... 
} 

這比使用volatile乾淨得多,而且更容易,當你移動你的簡單的端口概念證明分開類。查看我的博客Polling for Cancellation,瞭解更多信息。

相關問題