如何将计时器连接到不同的线程事件

时间:2016-10-11 08:21:03

标签: c# wpf events timer

我有一个应用程序,我必须让一些LED闪烁一些颜色和(调试)椭圆。根据事件驱动状态,我必须改变眨眼颜色。 计时器总是一样的:

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();
    }
}

所以简而言之,我的想法是:当检测到更改时,停止上一个计时器行为,更改它并恢复并开始。

但有些事情并不奏效。它行为奇怪,并试图更具体,它永远不会变黄。

如果我在断路器设置为运行的地方设置断点,我会看到它被击中但从未进入SetLeds例程。这个运行状态是从另一个线程设置的可能是这个原因吗?

因此,当发生运行事件时,计时器不会打勾。

提前感谢您的任何帮助

帕特里克

1 个答案:

答案 0 :(得分:0)

尝试在代码中的其他位置设置一个断点。然后检查ledTimer.Dispatcher.Thread&amp;你可能会看到“this.ledTimer.Dispatcher.Thread.ApartmentState”抛出了'System.Threading.ThreadStateException'类型的异常。

您需要从计时器所属的同一个线程设置新状态 - 您可以使用它自己的Dispatcher(或Gui线程上的任何其他对象)来设置计时器:

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