首先,抱歉我的英文寫作不好。C#:如果System.Windows.Forms.Timer間隔不足以完成工作,該怎麼辦?
假設我們有一個擁有計時器的勝利表單(C#)。定時器間隔已設置爲60000毫秒。所以它的滴答事件將會每1毫秒發射一次。假設我們已經寫了一個方法來處理叫做Timer1_Tick的tick事件。如果這項工作需要1分鐘才能完成,該怎麼辦?
首先,抱歉我的英文寫作不好。C#:如果System.Windows.Forms.Timer間隔不足以完成工作,該怎麼辦?
假設我們有一個擁有計時器的勝利表單(C#)。定時器間隔已設置爲60000毫秒。所以它的滴答事件將會每1毫秒發射一次。假設我們已經寫了一個方法來處理叫做Timer1_Tick的tick事件。如果這項工作需要1分鐘才能完成,該怎麼辦?
將進程的當前狀態存儲在字段或屬性中,並且只有當狀態沒有「正在運行」時才啓動進程。
另一個計時器事件可能會排隊,導致Timer1_Tick在返回後幾乎立即被調用。 (但是,IIRC,計時器滴答是最低優先級的消息之一,所以它可能會處理任何其他消息,它先排隊等待,除了可能繪製消息)。
請注意,如果您的函數運行時間超過2分鐘,則有可能(讀取:可能)只有最近的滴答聲將在隊列中。
如果您的打勾處理時間比定時器間隔長,您應該考慮提高間隔。無論採用哪種方式,您都應該在後臺線程中完成工作,並確保如果最後一個時間線的任務未完成,則不會啓動另一個線程。否則,最終可能會導致大量的線程相互減速,直到程序在自己的體重下崩潰。
因此,當您啓動作業並在計時器啓動時檢查標誌時設置一個標誌。如果標誌已設置,則在定時器處理程序中不執行任何操作。請記住在作業完成時清除標誌。
您是否正在剝離工作線程來完成這項工作?
設置一個標誌,允許您檢查長時間運行的作業是否已完成,並且只有在作業完成時才運行作業。不要忘記在完成長時間運行的作業後旗復位:
// field
private bool finishedWork = true;
public void Timer1_Tick(Object o, EventArgs e)
{
if (finishedWork)
{
finishedWork = false;
// do work
finishedWork = true;
}
}
另一種選擇是簡單地禁用操作之間定時器:
public void Timer1_Tick(Object o, EventArgs e)
{
if (finishedWork)
{
Timer1.Enabled = false;
// do work
Timer1.Enabled= true;
}
}
在Timer1_Tick,然後開始關閉計時器事後再啓用它?
你有幾種選擇,這裏的四我能想到的:
沒有正確的答案。你必須弄清楚什麼是最好的,適合你的情況。
我會爲#3作爲我的第一個解決方案。
有多種類型的計時器在.net中:一個是在System.Timers
命名空間,另一個是在System.Windows.Forms
命名空間,另一個在System.Threading
。
System.Windows.Forms.Timer
控件基於UI線程和消息循環,這意味着它將對定時器事件進行排隊,並且如果處理程序超出了時間間隔,它將在結束後立即調用。
其他兩個定時器都基於線程,並且非常準確。他們會在時間過後重新進入你的處理程序。
如此冗長的WinForms定時器阻塞操作不是一個好主意,因爲它基本上會阻塞消息隊列和所有相關的事情(尤其是UI)。 – Lucero 2010-06-29 09:10:58
您是否需要每分鐘執行一次作業,還是需要將作業執行時間縮短1分鐘?即。開始之間的一分鐘,還是一分鐘之間的工作?如果是後者,只需在開始執行作業時禁用定時器,然後啓用它,這將重置定時器。無論如何,我希望你認識到,每分鐘執行一項工作,工作時間超過1分鐘,都會造成問題。另外,在正常的基於非線程的計時器中執行1分鐘的作業不是一個好主意,你應該看看使用線程(例如BackgroundWorker)。 – 2010-06-29 09:15:42
@Lucero:你的建議是什麼?對於冗長的操作,請使用 – odiseh 2010-06-29 09:20:15