我对使用system.timers和线程的概念设计有疑问。
考虑以下伪代码(它在C#中,但是因为我问概念,我不检查语法的准确性)
class exam{
private Serialport sp;
private readonly object lckObj = new object();
System.Timer timer;
public exam()
{
// actually I think this lock is not needed as
// the object gets created on thread creation...
// a yay-nay on this would be cool too, I figure it
// can't hurt to lock
lock(lckObj)
{
// do stuff
sp = new Serialport(params);
sp.DataRecieved += sp_dataRec;
timer = new system.Timer(someNumber);
timer.Elapsed += timeElap;
timer.Enabled = true;
// also from my understanding in how enabled
// works, this is redundant and I can remove
timer.Start();
}
}
private void timeElap()
{
lock(lckObj)
{
if(sp.Closed) sp.Open();
}
}
private void sp_dataRec()
{
lock(lckObj)
{
//do stuff to process message
// set success bool
bool success = outcomeOfProcessing;
callResponse(success);
}
}
private void callResponse(bool success)
{
if(!sp.IsOpen) sp.Open();
// logic to assemble response hinged on success
sp.Write("something");
}
}
我要做的是让计时器通过并每隔几秒检查一次以确保端口没有关闭。这是因为“某些东西”不知道什么是关闭端口 - 通过附加端口监视器找到它,它只是随机弹出关闭。没有错误弹出或任何东西(没有计时器抑制错误,我正在寻找添加计时器)。不知道为什么会发生这种情况(也从来没有在代码中我.Close();端口)
然而,当我想到这个低谷时,我现在担心如果我锁定检查串口以检查状态,以及锁定它以发送消息 - 这将禁止我的数据接收句柄,或者它仍然会相应排队
例如我锁定串口以检查状态,稍微过了一会儿,可能会错过可能在pop上的数据字节而不是获取
0.1234。
我得到了
1234
注意点是开始/停止字节
编辑:我忘了提到我的另一个问题是Sytem.Timer抑制串口干扰的错误
Edit2:我从callResponse中删除了锁定 - 因为我再看一遍它对响应的调用将使用已经锁定的方法 - 所以它应该是线程安全的仍然 - 正确吗?
答案 0 :(得分:3)
SerialPort
缓冲数据。当您调用接收到的事件处理程序时,基础控件已经从串行端口读取数据并将其存储在内部缓冲区中。锁定不会导致问题,除非您按住它以使数据缓冲区填满。
那就是说,我必须重复我在评论中所说的内容:你提出的解决方案无法可靠地运作。如果程序外部的某些内容异步禁用串行端口,则无论程序处于何种状态,它都可以随时发生。您有一秒钟的计时器检查端口是否已关闭,如果是,请重新启动 - 打开它。这可能会解决问题"大部分时间,"但是不能保证在重新打开端口后立即关闭端口,或者在程序处于发送或接收数据的过程中关闭端口。请记住:您的代码不会执行实际的发送或接收,而是读取或写入由基础SerialPort
控件管理的缓冲区。
您确实需要找出导致串口关闭的原因,并防止这种情况发生。这是使您的程序可靠的唯一方法。