2014-01-23 87 views
0


我有一個按鈕,鼠標單擊事件處理程序。
按下按鈕(鼠標向下)時,啓動計時器以延遲模擬其他點擊。點擊運行位圖轉換,例如每次旋轉0.5次。
當按鈕被釋放(鼠標向上)時,定時器停止。
代碼在Button類:如何在定時器停止時停止剩餘動作?

private void TreatMouseDown(object sender, MouseEventArgs e) { 
    // Following clicks 
    _repeteTimer.Tick += (senderTick, eTick) => { 
     _repeteTimer.Stop(); 
     PerformClick(); 
     _repeteTimer.Interval = _nextDelay; 
     _repeteTimer.Start(); 
    }; 
    // First click 
    PerformClick(); 
    _repeteTimer.Interval = _firstDelay; 
    _repeteTimer.Start(); 
} 

private void TreatMouseUp(object sender, MouseEventArgs e) { 
    _repeteTimer.Stop(); 
} 

代碼窗口:

btnRotation1.Click += (sender, e) => PHOTO_Treat(1); 

private void PHOTO_Treat(int delta) { 
    if (!_inProgress) { 
     _photoRotation += delta * 0.5F; 
     PHOTO_Show(); 
    } 
} 

private void PHOTO_Show(){ 
    if (_inProgress) return; 
_inProgress= true; 

    // Make image treatments ... 

    _inProgress = false; 
} 

的問題是,在釋放按鈕後,再次出現了幾次改變,如果變換需要很長時間。
我該如何抑制剩餘?

+0

也許你可以嘗試一些其他場景。例如,讓'Timer'始終打開。設置一些標誌,在內部按下鼠標按鈕時,釋放時復位。如果設置了標誌,'Timer'將進行旋轉,否則不會。另一件事是重繪。而是**總是改變角度**,並開始用'Invalidate()'重新繪製(這意味着請*,只要有時間*,重新繪製這個控件)並且在OnPaint內部繼續角度,就像你做的那樣你沒有使用定時器來同步旋轉,而是依靠重繪,這就好像你不使用定時器 - >取決於PC的性能)。 – Sinatr

+0

使用OnPaint而不是定時器可以有效地適應重新繪製到pc性能。我牢記這個想法。謝謝。 – user3226852

回答

0

聽起來像你有一些嚴重的線程問題。

您可以通過檢查_repeteTimer.Enabled來檢查按鈕是否仍然關閉。

另外,添加一個鎖。即使只是爲了安全。

private readonly object SyncRoot = new object(); 

private void PHOTO_Show() 
{ 
    if (!_inProgress) 
    { 
     // race for a lock 
     lock (SyncRoot) 
     { 
      // check button state 
      if (!_repeteTimer.Enabled) 
      { 
       // button was released 
       return; 
      } 
      // else 
      try 
      { 
       _inProgress = true; 
       MakeImageTreatments(); 
      } 
      finally 
      { 
       _inProgress = false; 
      } 
     } 
    } 
} 
+0

「鎖定」聲明似乎是一個很好的解決方案,沒有額外的「點擊」累積,最終的增量是好的(不會增加太多)。謝謝 ! – user3226852

+0

它有助於理解定時器不會等待「Tick」處理程序完成,然後再次開始計數。這就是爲什麼你需要編寫自己的同步邏輯。這是一個很常見的情況,所以請確保你不會忘記它。 –