2009-09-23 123 views
3

我需要能夠爲我正在寫的應用程序每次禁用1.5秒按鈕。顯示圖像,用戶單擊按鈕,然後顯示另一圖像。我需要確保用戶不會再快速點擊按鈕。爲什麼這個C#計時器代碼不工作?

因此,在顯示圖像時,我調用這個函數:

//when a new image is displayed, start the timer and disable the 'done' button 
    //for 1.5 seconds, to force people to stop pressing next so quickly 
    System.Timers.Timer mTimer; 
    void TimerStart() { 
     Done.IsEnabled = false; 

     mTimer = new System.Timers.Timer(); 
     mTimer.Interval = 1500; 
     mTimer.Start(); 
     mTimer.Elapsed += new System.Timers.ElapsedEventHandler(TimerEnd); 
    } 

的TimerEnd代碼如下所示:

void TimerEnd(object sender, EventArgs eArgs) { 
     if (sender == mTimer){ 
      Done.IsEnabled = true; 
      mTimer.Stop(); 
     } 
    } 

的 'Done.IsEnabled' 線被擊中,但按鈕不能重新啓用,計時器不會停止發射。我在這裏做錯了什麼?如果重要,這是一個WPF應用程序。

+0

我在TimerEnd方法中看不到任何會再次啓用按鈕的代碼 – 2009-09-23 01:13:56

+0

除了方法的好壞之外,對於您的示例中的好方法,您應該添加事件處理程序(Elapsed + = ...) )在啓用事件觸發之前(Start())。 – 2009-09-23 01:19:01

+0

@ Ed--那是Done.IsEnabled調用。 @傑森 - 好點,我會換掉它。 – mmr 2009-09-23 01:23:06

回答

7

使用DispatcherTimer代替

DispatcherTimer timer = new DispatcherTimer(); 
timer.Interval = TimeSpan.FromMilliseconds(someInterval); 
timer.Tick += new EventHandler(someEventHandler); 
timer.Start(); 

private void someEventHandler(Object sender, EventArgs args) 
{ 
//some operations 
//if you want this event handler executed for just once 
// DispatcherTimer thisTimer = (DispatcherTimer)sender; 
// thisTimer.Stop(); 
} 
+0

良好的通話。謝謝。 – mmr 2009-09-23 01:23:45

1

計時器事件在不同的線程上產生。在使用winforms控件時,你需要確保你從他們被調用的同一個線程中獲得Invoke

+0

WPF,不是winforms。 – mmr 2009-09-23 01:15:19

+0

仍然適用於WPF – 2009-09-23 05:07:18

2

基本上你試圖去抖按鈕,以防止過多簡單的點擊。如果在短時間內再次點擊該按鈕,則忽略下一個事件,而不是使用計時器以毫秒爲單位保存以前的點擊時間。

+0

一個有趣的想法,當然也是一個合理的解決方案。 – mmr 2009-09-23 01:24:20

+0

這不是你想要忽略的事件,因爲你不知道它是否是最後的事件,直到間隔通過,然後你可能想要採取行動。你需要計時器!請參閱此處的'debounce'的定義:https://github.com/documentcloud/underscore/blob/master/underscore.js#LC555 – 2012-03-01 22:00:44

0

使用WPF時,不能保證對非UI線程上的UI控件所做的更新將按預期工作。在許多情況下,當你這樣做時你會得到一個例外。

在您的Timer經過處理,你需要使用的BeginInvoke/EndInvoke會的模式,並把你的按鈕實現的邏輯在那裏,以確保該代碼在UI線程上運行,而不是開始/結束調用

有一個SynchnornizationContext也可以通過致電SynchronizationContext.Current訪問。在進行定時器調用之前,您需要緩存這些內容,因爲SynchronizationContext.Current在非UI線程中將爲null。

This鏈接也對此進行了討論。

+0

WPF,而不是winforms。 – mmr 2009-09-23 01:37:11

+0

無論如何。開始/調用部分仍然適用。 WindowsFormsSynchronizationContext.Send不適用。我會編輯我的回答 – 2009-09-23 01:53:47

+0

@ Abhijeet--也許,但是當我在接受的答案中使用計時器代碼而不調用或使用任何其他線程代碼時,它就可以工作。因此,我認爲你的答案是錯誤的,或者不適用。 – mmr 2009-09-23 18:19:27