【问题标题】:locking messing up serialport handles锁定弄乱串口句柄
【发布时间】: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


【解决方案1】:

SerialPort 缓冲数据。在调用接收到的事件处理程序时,底层控件已经从串行端口读取数据并将其存储在内部缓冲区中。除非您将其持有太久以至于数据缓冲区已填满,否则锁定不会引起问题。

也就是说,我必须重复我在 cmets 中所说的话:无法使您提出的解决方案可靠地工作。如果您的程序外部的某些东西正在异步禁用串行端口,则无论您的程序处于何种状态,它都可能随时发生。您有一个一秒钟的计时器来检查端口是否关闭,如果是,请重新- 打开它。这可能会解决“大部分时间”的问题,但不能保证端口不会在您重新打开后立即关闭,或者它可能会在您的程序正在发送或接收数据时关闭。请记住:您的代码不会执行实际的发送或接收,而是读取或写入由底层SerialPort 控件管理的缓冲区。

您确实需要找出导致串行端口关闭的原因,并防止这种情况发生。这是使您的程序可靠的唯一方法。

【讨论】:

  • +1 是的 - 甚至可能是测试盒上的硬件或驱动程序问题,因此不会影响交付的应用程序。
  • 是的-我同意你的观点-双手捆绑-非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-11
  • 2017-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多