2010-06-29 101 views
0

首先,抱歉我的英文寫作不好。C#:如果System.Windows.Forms.Timer間隔不足以完成工作,該怎麼辦?

假設我們有一個擁有計時器的勝利表單(C#)。定時器間隔已設置爲60000毫秒。所以它的滴答事件將會每1毫秒發射一次。假設我們已經寫了一個方法來處理叫做Timer1_Tick的tick事件。如果這項工作需要1分鐘才能完成,該怎麼辦?

+3

如此冗長的WinForms定時器阻塞操作不是一個好主意,因爲它基本上會阻塞消息隊列和所有相關的事情(尤其是UI)。 – Lucero 2010-06-29 09:10:58

+0

您是否需要每分鐘執行一次作業,還是需要將作業執行時間縮短1分鐘?即。開始之間的一分鐘,還是一分鐘之間的工作?如果是後者,只需在開始執行作業時禁用定時器,然後啓用它,這將重置定時器。無論如何,我希望你認識到,每分鐘執行一項工作,工作時間超過1分鐘,都會造成問題。另外,在正常的基於非線程的計時器中執行1分鐘的作業不是一個好主意,你應該看看使用線程(例如BackgroundWorker)。 – 2010-06-29 09:15:42

+0

@Lucero:你的建議是什麼?對於冗長的操作,請使用 – odiseh 2010-06-29 09:20:15

回答

0

將進程的當前狀態存儲在字段或屬性中,並且只有當狀態沒有「正在運行」時才啓動進程。

1

另一個計時器事件可能會排隊,導致Timer1_Tick在返回後幾乎立即被調用。 (但是,IIRC,計時器滴答是最低優先級的消息之一,所以它可能會處理任何其他消息,它先排隊等待,除了可能繪製消息)。

請注意,如果您的函數運行時間超過2分鐘,則有可能(讀取:可能)只有最近的滴答聲將在隊列中。

如果您的打勾處理時間比定時器間隔長,您應該考慮提高間隔。無論採用哪種方式,您都應該在後臺線程中完成工作,並確保如果最後一個時間線的任務未完成,則不會啓動另一個線程。否則,最終可能會導致大量的線程相互減速,直到程序在自己的體重下崩潰。

1

因此,當您啓動作業並在計時器啓動時檢查標誌時設置一個標誌。如果標誌已設置,則在定時器處理程序中不執行任何操作。請記住在作業完成時清除標誌。

您是否正在剝離工作線程來完成這項工作?

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; 
    } 
} 
0

在Timer1_Tick,然後開始關閉計時器事後再啓用它?

2

你有幾種選擇,這裏的四我能想到的:

  1. 放棄目前的工作,開始新的一個。當然,如果當前的工作無法停止,這個問題的最大缺點就是。
  2. 在開始新作業之前等待當前作業完成。如果每個人花費超過一分鐘的時間,這可能會讓您留下一個未決作業隊列。
  3. 不要開始新的工作。讓當前的一個完成,然後等待下一個計時器間隔開始新的作業。
  4. 增加作業之間的時間間隔。這只是推遲了問題。

沒有正確的答案。你必須弄清楚什麼是最好的,適合你的情況。

我會爲#3作爲我的第一個解決方案。

0

有多種類型的計時器在.net中:一個是在System.Timers命名空間,另一個是在System.Windows.Forms命名空間,另一個在System.Threading

System.Windows.Forms.Timer控件基於UI線程和消息循環,這意味着它將對定時器事件進行排隊,並且如果處理程序超出了時間間隔,它將在結束後立即調用。

其他兩個定時器都基於線程,並且非常準確。他們會在時間過後重新進入你的處理程序。

相關問題