page contents

c# 如何禁用winapi串口

本文讲述了c# 如何禁用winapi串口!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

attachments-2022-10-PEmw88rJ633f8683ee2fb.png本文讲述了c# 如何禁用winapi串口!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

VC#中如果涉及到多线程,特别是大量的数据处理和界面更新时,如果简单强制的关闭串口,很可能会造成串口死掉。
串口无法关闭的原因是:要关闭串口的时候,有其它线程还在读取数据或者更新界面。
关键是:在准备关闭串口的时候,看看是否在接收和处理数据,如果是就等它处理完为止;在事件处理的最前面,判断如果是准备关闭串口的bool类型值,就不再进入数据接收和处理。

using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Timers;


namespace PortTesting
{
    /// <summary>
    /// 定义了一个委托类型
    /// </summary>
    public delegate void WhenGetNew();

    /// <summary>
    /// 串口封装类,Help By Wyz
    /// </summary>
    public class PortDataDisplay
    {
       /// <summary>
       /// 系统串口类
       /// </summary>
       public SerialPort serialPort = new SerialPort("COM1", 19200);
       /// <summary>
       /// 解析得到数据后触发事件
       /// </summary>
       public event WhenGetNew whenGetNew;
       /// <summary>
       /// 处理线程
       /// </summary>
       private SerialDataReceivedEventHandler threadCallHandler;
       /// <summary>
       /// 对外的数据类型定义
       /// </summary>
       public string dataSrc = "";
       /// <summary>
       /// 准备关闭串口=true
       /// </summary>
       private bool m_IsTryToClosePort = false;
       /// <summary>
       /// true表示正在接收数据
       /// </summary>
       private bool m_IsReceiving = false;
       

       /// <summary>
       /// 初始化
       /// </summary>
       public PortDataDisplay()
       {
       }

       /// <summary>
       /// 有参数的构造函数
       /// </summary>
       /// <param name="PortName">串口号,如"COM1"</param>
       /// <param name="BaudRate">波特率,如19200</param>
       public PortDataDisplay(string PortName, int BaudRate)
       {
           serialPort = new SerialPort(PortName, BaudRate);
       }

       /// <summary>
       /// 开始工作
       /// </summary>
       public void ConnectDeveice()
       {
           //0.注册事件
           serialPort.DataReceived -= OnSerialPortDataCome;
           serialPort.DataReceived += OnSerialPortDataCome;
           //1.再设置一下串口参数
           if (this.serialPort.IsOpen == false)
           {
               this.serialPort.ReadBufferSize = 1000;
               this.serialPort.ReceivedBytesThreshold = 1;//数据达到120的时候才就要触发事件,不行!!应该是数据来就触发
               //2.打开串口开始工作
               m_IsTryToClosePort = false;
               this.serialPort.Open();
           }
       }

       /// <summary>
       /// 结束工作
       /// </summary>
       public void DisconnectDeveice() // 关键和核心!!!
       {
           m_IsTryToClosePort = true;
           while (m_IsReceiving)
           {
               System.Windows.Forms.Application.DoEvents();
           }
           serialPort.Close();
       }

       /// <summary>
       /// 当通知到有数据达到120时处理(读取,与分析)
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void OnSerialPortDataCome(object sender, SerialDataReceivedEventArgs e)
       {
           if (m_IsTryToClosePort) // 关键!!!
           {
               return;
           }

           m_IsReceiving = true; // 关键!!!

           try
           {
               if (threadCallHandler == null)
               {
                   threadCallHandler = new SerialDataReceivedEventHandler(OnSerialPortDataCome);
               }

               //read
               dataSrc = serialPort.ReadExisting();//读出缓冲区所有数据
               if (dataSrc != "" && this.whenGetNew != null)
               {
                   this.whenGetNew();
               }
           }
           finally // 放在finally里面比较好。
           {
               m_IsReceiving = false; // 关键!!!
           }
       }
    }
}


 

使用的时候:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace PortTesting
{
    public partial class FrmMain : Form
    {
       /// <summary>
       /// 封装好的串口类
       /// </summary>
       private PortDataDisplay m_portDispl = new PortDataDisplay("COM1", 19200);

       public FrmMain()
       {
           InitializeComponent();
       }

       private void btnOpen_Click(object sender, EventArgs e)
       {
           if (btnOpen.Text == "打开串口")
           {
               m_portDispl.whenGetNew -= portDispl_whenGetNew;
               m_portDispl.whenGetNew += new WhenGetNew(portDispl_whenGetNew);
               m_portDispl.ConnectDeveice();
               btnOpen.Text = "关闭串口";
           }
           else if (btnOpen.Text == "关闭串口")
           {
               m_portDispl.DisconnectDeveice();
               btnOpen.Text = "打开串口";
           }
       }

       /// <summary>
       /// 事件
       /// </summary>
       private void portDispl_whenGetNew()
       {
           WhenGetNew ehan = delegate
           {
               txtDisplay.AppendText(m_portDispl.dataSrc);
           };

           try
           {
               if (InvokeRequired)
               {
                   this.Invoke(ehan);
               }
           }
           catch
           {
           }
       }


       private void btnClear_Click(object sender, EventArgs e)
       {
           txtDisplay.Clear();
       }
    }
}

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg



  • 发表于 2022-10-07 09:53
  • 阅读 ( 256 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1474 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章