定时器开关失效问题

云外缘 2019-05-16 04:57:40
现象:
当与下位机通信正常,且上位机设定参数与下位机内部参数不一致、再发送修改参数命令成功、再重启(重启下位机无返回,只能用超时继续下一步)时,超时时钟便无法正常进入Tick处理,此时超时时钟可以修改Interval,但不能修改Enable。超时时钟一直处于开状态。
而当下位机不存在时,超时时钟可以在“内部命令.读取全参数”时超时进入Tick处理。

请教这是什么情况?

声明:

private System.Windows.Forms.Timer 超时时钟 = new System.Windows.Forms.Timer();


到时处理:

private void 超时处理(object sender, EventArgs e)
{
内部命令 临时 = 命令;
命令 = 内部命令.无;
超时时钟.Enabled = false;
switch (临时)
{
case 内部命令.核对全参数:
MessageBox.Show("读出无响应!", "超时", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case 内部命令.写入全参数:
// 出错提示
break;
case 内部命令.读取全参数:
// 出错提示
break;
case 内部命令.写入网号:
// 出错提示
break;
case 内部命令.写入信道:
// 出错提示
break;
case 内部命令.模块重启:
{
byte[] 协议_查询主从机状态 = new byte[5] { 0xAA, 0xA1, 0x00, 0x00, 0xFF };
超时时钟.Interval = 300;
命令 = 内部命令.重启检测;
超时时钟.Enabled = true;
串口.Write(协议_查询主从机状态, 0, 协议_查询主从机状态.Length); // 发重启检测查询命令
}
break;
case 内部命令.重启检测:
// 出错提示
break;
}
if (!超时时钟.Enabled) 引用委托更新状态(false);
}


串口接收:

private void 串口接收数据(object sender, SerialDataReceivedEventArgs e)
{
try
{
Thread.Sleep(15); // 避免帧读断情况
串口接受的数据 = new byte[串口.BytesToRead];
串口.Read(串口接受的数据, 0, 串口接受的数据.Length);
串口.DiscardInBuffer();
switch (命令)
{
case 内部命令.无:
引用委托发送一个消息(MSG.消息_收到串口数据);
break;
case 内部命令.写入全参数:
{
超时时钟.Enabled = false;
bool 写入成功 = true;
if (串口接受的数据[6] != 0x00) 写入成功 = false;

if (写入成功)
{
byte[] 协议_重启命令 = new byte[4] { 0xAA, 0xC9, 0x00, 0xFF};
超时时钟.Interval = 1500; // 实测重启时间很短
命令 = 内部命令.模块重启;
for (int i = 0; i < 8; i++) 协议_重启命令[8] += 协议_重启命令[i];
超时时钟.Enabled = true; // 重启等待重启完成
串口.Write(协议_重启命令, 0, 协议_重启命令.Length); // 重启模块
}
else
{
// 出错提示
}
}
break;
case 内部命令.读取全参数:
{
if (串口接受的数据.Length >= 全参数字节数)
{
for (int i = 0, j = 0; i < 串口接受的数据.Length; i++, j++) 全参数[i] = 串口接受的数据[j];
超时时钟.Enabled = false;
if (全参数与配置不同())
{
修改全参数();
命令 = 内部命令.写入全参数;
超时时钟.Interval = 800;
超时时钟.Enabled = true;
串口.Write(全参数, 0, 全参数.Length); // 写全参数
}
else
{
// 进入正常工作
}
}
else
无线模块自检结束后("读信息错误");
}
break;
case 内部命令.重启检测:
if (串口接受的数据.Length >= 6)
{
if (重启反馈正确())
{
// 进入正常工作
}
else
{
// 出错提示
}
}
else
{
// 出错提示
}
break;
case 内部命令.写入信道:
// 出错提示
break;
}
}
catch (System.Exception ex)
{
// 出错提示
}
}



打开串口时:

public void 打开串口(string 串口名)
{
串口 = new SerialPort(串口名, 19200, Parity.None, 8, StopBits.One);
try
{
串口.Open();
串口.DiscardInBuffer();
串口.DiscardOutBuffer();
打开 = true;
串口.DataReceived += 串口接收数据;

超时时钟.Enabled = false;
超时时钟.Interval = 1800;
命令 = 内部命令.读取全参数;
超时时钟.Enabled = true;
串口.Write(协议_读取全参数, 0, 协议_读取全参数.Length);
}
catch
{
串口.Dispose();
串口 = null;
// 出错提示
}
}


创建时:

超时时钟.Tick += new System.EventHandler(超时处理);
超时时钟.Enabled = false;
...全文
612 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
云外缘 2019-05-23
  • 打赏
  • 举报
回复
引用 8 楼 水边2 的回复:
没认真看你的代码,给你提个调试的思路, 你启动一个独立线程,每秒输出一下Timer的状态, 看看什么时间点,它被启动了, 基本上,肯定是你的程序在某个地方启动了它。
代码全在上面了。现在我已经用窗体拖的定时器加委托(方法完全同类内部申请的定时器)解决了这个问题,但是作为一个程序猿,我对类内部申请的定时器有问题表示困惑。
游北亮 2019-05-20
  • 打赏
  • 举报
回复
没认真看你的代码,给你提个调试的思路, 你启动一个独立线程,每秒输出一下Timer的状态, 看看什么时间点,它被启动了, 基本上,肯定是你的程序在某个地方启动了它。
云外缘 2019-05-20
  • 打赏
  • 举报
回复
这问题没人回答么?真的可惜了。我尝试过代理,FORM中拖入的定时器可以正常工作,类中声明的定时器还是不行。真希望有一个合理的解释。
云外缘 2019-05-18
  • 打赏
  • 举报
回复
引用 5 楼 m0_37646670 的回复:
进断点一步步看呗,我估计是你窗口上点关闭timer,但是程序里又打开了timer,只是看起来想无法关闭
单步调试过的,不是那种情况
m0_37646670 2019-05-18
  • 打赏
  • 举报
回复
进断点一步步看呗,我估计是你窗口上点关闭timer,但是程序里又打开了timer,只是看起来想无法关闭
云外缘 2019-05-17
  • 打赏
  • 举报
回复
引用 2 楼 以专业开发人员为伍 的回复:
await Task.Delay 异步机制可以完全取代 timer 编程机制,而且编程简单直接,不大会纠结那么多问题和 bug。用直接的 await Task.Delay 异步编程重新描述问题解决思路伪代码更好。
感觉await处理两个相互独立的耗时事件比较方便,而我这个在计时上是相互独立,但是阶段上是紧密关联,想来想去总觉得await实现上很困难…… 而关于Timer的使用,或许也就是个使用上存在违例的问题,希望能有高手慧眼识BUG,这样我也省事……
  • 打赏
  • 举报
回复
await Task.Delay 异步机制可以完全取代 timer 编程机制,而且编程简单直接,不大会纠结那么多问题和 bug。用直接的 await Task.Delay 异步编程重新描述问题解决思路伪代码更好。
云外缘 2019-05-17
  • 打赏
  • 举报
回复
C#此处十分诡异,为了验证意外代码段对定时器的影响,我特地从视窗拉了一个Timer,然后尝试打开并MessageBox一个信息,出现了各种不确定结果。此时截图是,下一句打红下划线的语句不能去掉,去掉,则定时器不能进入到时处理,加上就可以。 而此前的调试时,Timer1只要在if(写入成功)中即不可触发,而必须写在if之上。 从这个现象来看,不知道是不是这里因为代码优化方面的问题导致了什么意外……
云外缘 2019-05-16
  • 打赏
  • 举报
回复
调试时,当“超时时钟”异常后,可修改Interval的值,但是不能修改Enable的值,也就是无法关闭。

111,093

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧