2016-10-11 20 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

相关问题