锁定乱码串口句柄

时间:2014-08-04 16:01:57

标签: c# multithreading timer serial-port

我对使用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中删除了锁定 - 因为我再看一遍它对响应的调用将使用已经锁定的方法 - 所以它应该是线程安全的仍然 - 正确吗?

1 个答案:

答案 0 :(得分:3)

SerialPort缓冲数据。当您调用接收到的事件处理程序时,基础控件已经从串行端口读取数据并将其存储在内部缓冲区中。锁定不会导致问题,除非您按住它以使数据缓冲区填满。

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

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