我有一个子程序,它启动两个计时器中的一个(取决于“区域”条件)。这个名为'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;
}
}
答案 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发回更改请求,这将在正确的线程上完成工作。