2013-06-21 35 views
4

我有2個全球System.Windows.Forms.Timer在我的表格。兩者都是在窗體的構造函數中初始化的。但尚未開始。構造函數啓動新線程,該線程啓用並啓動兩個定時器。顯然這是所有跨線程,但它不會引發任何跨線程異常。但它甚至不起作用。它不會觸發Timer.Tick方法。下面是代碼:計時器不在十字螺紋工作

第1種方法:

在形式的構造函數:

KeepMeAliveTimer = new Timer(); //timer 1 
    KeepMeAliveTimer.Interval = 15000;    
    KeepMeAliveTimer.Tick += KeepMeAlive; 
    timer1 = new Timer(); //timer 2 
    timer1.Interval = 15000; 
    timer1.Tick += timer1_Tick; 
    //started a new thread 

在新THEAD:

//after performing some tasks, it enables the timers 
    KeepMeAliveTimer.Enabled = true; //timer 1 
    KeepMeAliveTimer.Start(); 
    timer1.Enabled = true; //timer 2 
    timer1.Start(); 

但它沒有啓動起來定時器的Tick事件和甚至沒有拋出任何異常。

第2種方法:

但是當我初始化並在同一個線程(主線程)啓用Timers他們是完美的工作:

KeepMeAliveTimer = new Timer(); //timer 1 
    KeepMeAliveTimer.Interval = 15000;    
    KeepMeAliveTimer.Tick += KeepMeAlive; 
    KeepMeAliveTimer.Enabled = true; 
    KeepMeAliveTimer.Start(); 
    timer1 = new Timer(); //timer 2 
    timer1.Interval = 15000; 
    timer1.Tick += timer1_Tick; 
    timer1.Enabled = true; 
    timer1.Start(); 

現在的問題是;如果甚至沒有任何異常,爲什麼第一種方法不起作用?

+0

例外ae(調試幫助)。不保證它是密封的。您的代碼不是線程安全的,並且不起作用。 '1 + 1 = 2'。 –

+0

要完成,請指定哪個Timer類(名稱空間)。 .NET至少有3. –

+0

System.Windows.Forms.Timer依賴於Windows消息隊列被推送到它我相信。如果它在沒有訪問消息隊列的線程上,則它無法執行任何操作。 – Brad

回答

9

Timer類是線程安全的,但不像您期望的那樣。在工作線程上調用Start()方法確實會啓動計時器。這個類通過創建一個隱藏窗口來完成,因此它可以調用SetTimer的winapi函數並在完成時接收WM_TIMER消息。

但是,如果沒有人正在收聽該消息,則無法提高Tick事件。你不會,當然你沒有在該線程上調用Application.Run()。因此,您不應該在工作線程上啓動計時器。如果需要,使用Control.BeginInvoke在UI線程上啓動它。

或者使用System.Threading.Timer或System.Timers.Timer,它們不依賴於消息循環。你必須正確地聯鎖,他們的Elapsed事件或回調運行在另一個線程上。哪種解決方案會導致另一個問題。

+0

但是'Timer'類沒有'BeginInvoke'方法 – Shaharyar

+0

不,你的表單有一個。 –

+0

很好的答案!清楚的概念和實施完美 – Shaharyar