【发布时间】:2014-08-04 16:01:56
【问题描述】:
我有一个关于使用 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(); 端口)
但是,当我在思考这个问题时,我现在担心如果我锁定以检查串行端口以检查状态,以及锁定它以发回消息 - 这会抑制我接收到的数据句柄,还是仍然会相应地排队
例如,我锁定串行端口以检查状态,然后稍稍错过可能会丢失我在 pops 中的数据字节而不是获取
.1234.
我明白了
1234.
注意点是开始/停止字节
编辑:我忘了提到我的另一个问题是 Sytem.Timer 抑制串行端口干扰的错误
Edit2:我从 callResponse 中删除了锁-当我再次查看它时,对响应的调用将使用已锁定的方法-因此它仍然应该是线程安全的-正确吗?
【问题讨论】:
-
I am not checking syntax for accuracy:好的,但这使得很难判断您发布的代码中的错误是否是您真实代码中的实际错误。例如,您在exam中创建SerialPort,但它是该方法的本地。它在其他任何地方都无法访问。我认为这只是“没有检查准确性”的事情,但我不知道。请发布至少是有效代码的内容。 -
This has come about because "something" no clue what is closing the port。我猜……USB/串口适配器? -
如果你的车上有一个轮胎会突然爆胎,你会带一个打气筒给它重新充气,或者你会修理该死的轮胎我>?您在这里的检查关闭和重新打开技术无法可靠地工作。关闭端口的任何东西都可能在发送或接收操作的中间关闭它,这将导致数据不完整。你需要找到随机关闭的原因并修复它,而不是试图用无法工作的东西来修补它。
-
SerialPort缓冲数据。在调用您的接收事件处理程序之前,它将已经接收到数据并将其存储在内部缓冲区中。所以锁不会引起问题,除非你持有它太久以至于数据缓冲区填满。 -
我理解权宜之计的问题。我也正在处理一些通过大量快速更改演变而来的代码。我所说的仍然成立:你不能让你的代码可靠地工作,因为端口可能随时关闭:例如,在你打开端口后 100 毫秒,或者在发送或接收数据的中间的某个地方。你真的需要追查原因,因为修补它是不可能的。
标签: c# multithreading timer serial-port