使用Monitor排他锁,用多线程控制串口收发

项目背景:

公司要做一个温控软件,需要协调三个串口同时收发,控制三个温控模块,重点是程序需要在查询温度的同时,还要下发控制指令给模块(升降温指令),这两个操作都得一写一读,因为它们返回的数据格式可以说是毫不相关,写在串口接收事件里的话没办法对接收的数据做一个有效的处理。

下发升降温指令的时间是不确定的,只能单独开一个线程来做,查询又执行的很快,50ms一次,很有可能出现两个线程几乎同时给串口写指令,又同时在读。这时候如果升降温线程读出来的是温度查询的返回值,温度查询那块读出来的又是升降温指令的返回值的话,程序就乱套了。

所以必须要加锁,才能确保程序在每次串口写操作后必须完成读操作后,才能进行下次对串口的操作,否则下次操作就一直等待,直到上次操作完成。

示例代码:

        private object obj = new object();

        /// <summary>
        /// 按指令设置参数
        /// </summary>
        /// <param name="cmd"></param>
        /// <returns></returns>
        public bool SetValue(string cmd)
        {
            try
            {
                while (!(Monitor.TryEnter(obj)))  
                {
                    //线程锁占用,等待后再次进入while循环
                    Thread.Sleep(10);
                }
                serialPortHelper.SendString(cmd);
                string receive = serialPortHelper.ReadToStr("\r");
                if (receive == "CMD:REPLY=1@0")
                {
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                return false;
            }
            finally
            {
                Monitor.Exit(obj);  //线程锁释放
            }
        }

        /// <summary>
        /// 查询当前温度
        /// </summary>
        public double QueryCurrTemp()
        {
            try
            {
                while (!(Monitor.TryEnter(obj)))
                {
                    //线程锁占用,等待后再次进入while循环
                    Thread.Sleep(10);
                }
                serialPortHelper.SendString("TC1:TCACTUALTEMP?@0\r");
                string currTempStr = serialPortHelper.ReadToStr("\r");
                 //对接收的数据进行处理
                double currTemp = Convert.ToDouble(Regex.Match(currTempStr, @"(?<==).*(?=@)").Value);
                return currTemp;
            }
            catch (Exception)
            {
                return -999;
            }
            finally
            {
                Monitor.Exit(obj);
            }
        }

代码中串口读写是我写的类,在复制的时候会报错,换成自己的读写类就好了

Monitor.TryEnter(obj)表示,查询现在obj对象是不是锁定的状态,如果是锁定的状态,值就是false,那么就进入这个While循环,等待10ms之后再次查看是否仍然锁定,直到obj解锁

                while (!(Monitor.TryEnter(obj)))  
                {
                    //线程锁占用,等待后再次进入while循环
                    Thread.Sleep(10);
                }

我这里由于查询周期是50ms,所以我延时设置成了10ms,大家可以把延时设置成100或更多以适应自己的程序。在执行完所有的操作后,将obj的锁释放,这样在等候的其他程序就可以操作串口了。

            finally
            {
                Monitor.Exit(obj);  //线程锁释放
            }

以上是对单个串口进行加锁,解锁操作,以实现读写的控制,如何控制三个串口同时收发,读取数据,并作为三条曲线显示在同一个Chart控件中,我会找个时间再开一篇文章,感兴趣的朋友可以留言

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XX_YYDS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值