Timer表示它已启用,但从未执行

时间:2012-03-31 00:14:25

标签: c# winforms timer

我有一个子程序,它启动两个计时器中的一个(取决于“区域”条件)。这个名为'CheckAndActivateRelays'的子本身由串行端口_DataReceived事件调用。我正在插入断点来帮助我进行故障排除,并且看到tmrSoundSirensAfterDelay.Start()行正在成功执行,并且计时器的状态甚至更改为启用。但是,关联的Tick事件永远不会执行其中包含的任何代码。

如果我通过在button24的click事件中调用sub来做同样的事情,那么它可以完美地工作。所有内容都在同一个表单上,没有任何线程进程。

任何?感谢

private void checkAndActivateRelays(int zoneNumber)
   {

       if (globalFullAlarmSet || globalNightAlarmSet || globalDoorsAlarmSet)
           {
               if (zoneNumber == 1) //Entry zone
               {
                   //kick off a timer after delay specified in Settings1 file,
                   if (Settings1.Default.alarmSirenDurationInMinutes != 0)
                   {
                       //activates the relays if global alarm flags are still set to true 
                       //(i.e. user has not entered code in time)
                       globalAlarmEntryDurationTicks = 0;                           
                       tmrSoundSirensAfterDelay.Start();

                   }
               }
               else //If any other zone is activated during alarm set condition
               {
                   if (Settings1.Default.alarmSirenDurationInMinutes != 0)
                   {
                       //Output to relays 1 & 2
                       spIOCard.Write("~out10=1~");
                       spIOCard.Write("~out11=1~");

                       //then close after duration from Settings1 file
                       globalAlarmSirenDurationTicks = 0;
                       tmrSoundSirens.Start();
                   }
               }

           }

   }

   private void tmrSoundSirensAfterDelay_Tick(object sender, EventArgs e)
   {
       globalAlarmEntryDurationTicks = globalAlarmEntryDurationTicks + 1;

       if (globalAlarmEntryDurationTicks == Settings1.Default.alarmEntryDelayInSeconds) //Value from Settings1 file
       {
           spIOCard.Write("~out10=1~");
           spIOCard.Write("~out11=1~");
           globalAlarmEntryDurationTicks = 0;
           tmrSoundSirensAfterDelay.Stop();
           tmrSoundSirens.Start();
       }
   }

   private void tmrSoundSirens_Tick(object sender, EventArgs e)
   {           
       globalAlarmSirenDurationTicks = globalAlarmSirenDurationTicks + 1;

       if (globalAlarmSirenDurationTicks == (Settings1.Default.alarmSirenDurationInMinutes * 5))  //*60 Value from Settings1 file
       {
           spIOCard.Write("~out10=0~");
           spIOCard.Write("~out11=0~");               
           globalAlarmSirenDurationTicks = 0;
           tmrSoundSirens.Stop();
       }
   }



private void button24_Click(object sender, EventArgs e)
   {
       globalFullAlarmSet = true;
       checkAndActivateRelays(1);
   }

串行端口数据接收代码:

 private void spIO_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
       RxString = spIOCard.ReadExisting();

       if (RxString == "~in00=1~")
       {
           checkAndActivateRelays(1);
           button10.BackColor = System.Drawing.Color.Red;               
       }

       if (RxString == "~in00=0~")
       {
           button10.BackColor = System.Drawing.Color.LightGray;
       }

       if (RxString == "~in01=1~")
       {
           checkAndActivateRelays(2);
           button11.BackColor = System.Drawing.Color.Red;
       }

       if (RxString == "~in01=0~")
       {
           button11.BackColor = System.Drawing.Color.LightGray;
       }

       if (RxString == "~in02=1~")
       {
           button12.BackColor = System.Drawing.Color.Red;
       }

       if (RxString == "~in02=0~")
       {
           button12.BackColor = System.Drawing.Color.LightGray;
       }

}

3 个答案:

答案 0 :(得分:1)

您使用DataReceivedEvent后需要考虑的事情。根据MSDN,它是在辅助线程上引发的。这可能会导致您的问题。

  

当数据出现时,在辅助线程上引发DataReceived事件   从SerialPort对象接收。因为这个事件是在一个   辅助线程,而不是主线程,试图修改一些   主线程中的元素,如UI元素,可以引发一个   线程异常。如果有必要修改main中的元素   表单或控件,使用Invoke发回更改请求,这样做   正确的线程上的工作。

答案 1 :(得分:0)

由于调用Start()不是问题,因此定时器设置是您需要查看的位置。确保处理tick事件并设置间隔。

 myTimer.Tick += new EventHandler(TimerEventProcessor);

   // Sets the timer interval to 5 seconds.
   myTimer.Interval = 5000;
   myTimer.Start();

答案 2 :(得分:-1)

此处的关键是您在SerialPort DataReceived事件中执行此操作。此事件在单独的线程上触发。这很重要,因为您可能在主线程上注册了Tick事件,但是您在另一个上启动了计时器。您需要在Tick函数中注册checkAndActivateRelays事件。那应该很开心。

  

从SerialPort对象接收数据时,在辅助线程上引发DataReceived事件。因为此事件是在辅助线程而不是主线程上引发的,所以尝试修改主线程中的某些元素(例如UI元素)可能会引发线程异常。如果有必要修改主窗体或控件中的元素,请使用Invoke发回更改请求,这将在正确的线程上完成工作。