C# 锁定搞乱了serialport句柄
我有一个关于使用system.Timer和线程的概念设计的问题 考虑下面的伪代码(它是C语言的,但我问的是概念性的,我没有检查语法的准确性) 我要做的是让计时器通过,每隔几秒钟检查一次,确保端口没有关闭。这是因为“某物”不知道关闭端口的是什么-通过连接端口监视器发现这一点,它只是随机弹出关闭。没有错误弹出或任何事情(没有定时器抑制错误,我正在寻找添加定时器)。不知道为什么会发生这种情况(代码中也从来没有I.Close();调用端口) 然而,当我在思考这个问题时,我现在担心的是,如果我锁定serialport以检查状态,并锁定它以发送消息回来,这会抑制我的数据接收句柄,还是它仍然会相应地排队 例如,我锁定串行端口以检查状态,然后在足够短的时间后,可能会丢失pops中的字节数据,而不是获取数据 1234 我明白了 1234 注意点是开始/停止字节 编辑:我忘了提到我的另一个担忧是系统定时器抑制串口干扰的错误C# 锁定搞乱了serialport句柄,c#,multithreading,timer,serial-port,C#,Multithreading,Timer,Serial Port,我有一个关于使用system.Timer和线程的概念设计的问题 考虑下面的伪代码(它是C语言的,但我问的是概念性的,我没有检查语法的准确性) 我要做的是让计时器通过,每隔几秒钟检查一次,确保端口没有关闭。这是因为“某物”不知道关闭端口的是什么-通过连接端口监视器发现这一点,它只是随机弹出关闭。没有错误弹出或任何事情(没有定时器抑制错误,我正在寻找添加定时器)。不知道为什么会发生这种情况(代码中也从来没有I.Close();调用端口) 然而,当我在思考这个问题时,我现在担心的是,如果我锁定seri
Edit2:我从callResponse中移除了锁-我再次查看它时,对响应的调用将使用已锁定的方法-因此它仍然应该是线程安全的-正确吗?串行端口缓冲数据。在调用接收到的事件处理程序时,基础控件已从串行端口读取数据并将其存储在内部缓冲区中。锁定不会导致问题,除非您将其保持足够长的时间,以使数据缓冲区填满 话虽如此,我必须重复我在评论中所说的:你提出的解决方案无法可靠地发挥作用。如果程序外部的某些东西正在异步禁用串行端口,则无论程序处于何种状态,它都可能随时发生。您有一个1秒计时器,用于检查端口是否关闭,如果关闭,则重新打开。这可能会“大部分时间”解决这个问题,但不能保证在重新打开端口后,端口不会立即关闭,或者当程序处于发送或接收数据的中间时,端口可能被关闭。请记住:您的代码不执行实际的发送或接收,而是读取或写入由底层
SerialPort
控件管理的缓冲区
您确实需要找出导致串行端口关闭的原因,并防止这种情况发生。这是使您的程序可靠的唯一方法。
我没有检查语法的准确性
:好的,但这使得很难判断您发布的代码中的错误是否是您真实代码中的实际错误。例如,您可以在考试
中创建串行端口
,但它是该方法的本地端口。其他任何地方都找不到。我想这只是“没有检查准确性”的事情,但我不知道。请发布至少是有效代码的内容。之所以出现这种情况,是因为“某物”不知道是什么关闭了端口。
。我猜…USB/串行端口适配器?如果你的车上有一个轮胎会在随机时间突然漏气,你会带一个泵让它重新充气,还是你会修理这个该死的轮胎?您在此处对关闭和重新打开技术的检查无法可靠地工作。无论是关闭端口,都可以在发送或接收操作的中间关闭它,这会导致数据不完整。您需要找到随机关闭的原因并修复它,而不是尝试用无法正常工作的东西修补它。SerialPort
缓冲数据。在调用接收事件处理程序之前,它已经接收到数据并将其存储在内部缓冲区中。所以这个锁不会引起问题,除非你保持它的时间太长以至于数据缓冲区被填满。我理解这个权宜之计的问题。一、 我也在使用一些经过大量快速修改的代码。我所说的仍然是:您不能使您的代码可靠地工作,因为端口可以在任何时候关闭:例如在打开端口后100毫秒,或者在发送或接收数据中间的某个地方。你真的需要找出原因,因为修补不可能奏效。+1是的-甚至可能是测试盒上的硬件或驱动程序问题,因此不会影响交付的应用程序。是的-我同意你的看法-双手绑在一起-非常感谢!
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");
}
}