2016-10-11 43 views
0

我有一個應用程序,我必須讓一些leds閃爍一些顏色和(調試)一個橢圓。根據事件驅動的狀態,我必須改變眨眼的顏色。 計時器始終是相同的:如何將一個計時器連接到不同的線程事件

DispatcherTimer ledTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) }; 

但根據ledState值其行爲變化。而且那個根據外部事件而改變。

public eLedState _ledState; 
EventHandler ehLedTimer = null; 
eLedState LedState 
{ 
    get { return _ledState; } 
    set 
    { 
     ledTimer.Stop(); 
     ledTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) }; 

     if (ehLedTimer != null) 
      ledTimer.Tick -= ehLedTimer; 

     int counter = 0; 
     _ledState = value; 

     string WHITE = "255,255,255,1,0"; 
     string GREEN = "0,255,0,1,0"; 
     string RED = "255,0,0,1,0"; 
     string BLUE = "0,0,255,1,0"; 
     string YELLOW = "255,255,0,1,0"; 
     string OFF = "0,0,0"; 

     Serializers.Logger.WriteLog("LedState = " + LedState); 

     switch (_ledState) 
     { 
      case eLedState.IDLE: SetLeds(WHITE); break; 
      case eLedState.CONNECTING: 
       ehLedTimer = (sender2, args) => 
       { 
        switch (counter) 
        { 
         case 0: SetLeds(RED); counter++; break; 
         case 1: SetLeds(GREEN); counter++; break; 
         case 2: SetLeds(BLUE); counter = 0; break; 
        } 
       }; 
       break; 
      case eLedState.RUNNING: 
       ehLedTimer = (sender2, args) => { SetLeds(YELLOW); }; <-----HERE PROBLEM 
       break; 
      case eLedState.OUT_TOLERANCE: 
       ehLedTimer = (sender2, args) => 
       { 
        switch (counter) 
        { 
         case 0: SetLeds(RED); counter++; break; 
         case 1: SetLeds(WHITE); counter = 0; break; 
        } 
       }; 
       break; 
      case eLedState.IN_TOLERANCE: 
       ehLedTimer = (sender2, args) => 
       { 
        switch (counter) 
        { 
         case 0: SetLeds(GREEN); counter++; break; 
         case 1: SetLeds(WHITE); counter = 0; break; 
        } 
       }; 
       break; 
      case eLedState.PAUSED: 
       ehLedTimer = (sender2, args) => 
       { 
        switch (counter) 
        { 
         case 0: SetLeds(WHITE); counter++; break; 
         case 1: SetLeds(OFF); counter = 0; break; 
        } 
       }; 
       ledTimer.Start(); break; 
      case eLedState.ERROR: 
       ledTimer.Tick += (sender2, args) => 
       { 
        switch (counter) 
        { 
         case 0: SetLeds(RED); counter++; break; 
         case 1: SetLeds(OFF); counter = 0; break; 
        } 
       }; 
       break; 
      case eLedState.AWAITING_AUTOSTART: 
       ledTimer.Tick += (sender2, args) => 
       { 
        switch (counter) 
        { 
         case 0: SetLeds(RED); counter++; break; 
         case 1: SetLeds(GREEN); counter = 0; break; 
        } 
       }; 
       break; 

      default: 
       break; 
     } 
     ledTimer.Tick += ehLedTimer; 
     ledTimer.Start(); 
    } 
} 

因此,在短期我的想法是:當變化來檢測站前面的計時器行爲,改變它,恢復和啓動。

但有些東西不行。它行爲怪異,試圖更具體,它永遠不會變黃。

如果我在ledstate設置爲正在運行的位置放置一個斷點,我會發現它已被擊中但從未進入SetLeds例程。這種運行狀態是從另一個線程設置的,這可能是原因嗎?

因此,簡而言之,當運行事件被觸發時,定時器不打勾。

預先感謝您的任何幫助

帕特里克

+2

當LedState setter在另一個線程中調用,DispatcherTimer與該線程的關聯創建。然後它會在該線程中調用它的Tick處理程序,這不是UI線程,因此無法訪問任何代表LED的UI元素。除此之外,我覺得你的方法太複雜了。爲什麼不簡單評估一個Tick處理程序的每次調用中的LedState屬性?它根本不需要任何性能。 – Clemens

+0

非常感謝。你的提示使我找到了正確的解決方案。你可能想把它作爲答案發布...... – Patrick

回答

0

嘗試把一個破發點,在其他一些點在你的代碼&然後檢查ledTimer.Dispatcher.Thread &你可能會看到「此.ledTimer.Dispatcher.Thread.ApartmentState'拋出了一個'System.Threading.ThreadStateException'類型的異常。

您需要設置在同一個線程的新狀態的定時器的歸屬 - 你可以得到定時器與它自己的調度員設置(或GUI線程上任何其他對象):

ledTimer.Dispatcher.Invoke(() => LedState = eLedState.RUNNING); 
+0

對不起,但我已經這樣做了,正如我說的那樣行爲奇怪 – Patrick

+0

您需要將代碼中的其他點放在代碼中,這些代碼將在狀態被設置爲運行 - 那麼你將能夠看到新的計時器線程發生了什麼。我設法通過設置狀態來設法讓您的代碼運行。 – PaulF

相關問題