如何安全关闭串口

转载自http://blog.sina.com.cn/s/blog_4c8bb86b0100e5rw.html


串口无法关闭的原因是:要关闭串口的时候,有其它线程还在读取数据或者更新界面。
关键是:在准备关闭串口的时候,看看是否在接收和处理数据,如果是就等它处理完为止;在事件处理的最前面,判断如果是准备关闭串口的bool类型值,就不再进入数据接收和处理。

 

2010.03.27 更新 Help By Wyz. I appreciate it !!!

 

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();
        }
    }
}

 


### 回答1: 要使用 JavaScript 关闭串口连接,您需要使用浏览器的 Serial API。 首先,您需要获取串口连接的句柄。要做到这一点,您可以使用 navigator.serial.requestPort() 方法,该方法将返回一个 Promise 对象,其中包含可用的串口端口的列表。您可以使用以下代码获取串口端口的列表: ``` navigator.serial.requestPort().then(function(port) { // 这里的 port 变量是串口连接的句柄 // 您可以使用它来进行其他操作 }); ``` 一旦您获取了串口连接的句柄,您就可以使用 port.close() 方法来关闭连接。例如: ``` navigator.serial.requestPort().then(function(port) { // 关闭串口连接 port.close(); }); ``` 请注意,浏览器的 Serial API 目前仍处于实验阶段,并且只有部分浏览器支持它。您可以在此处查看支持 Serial API 的浏览器列表:https://caniuse.com/#feat=mdn-api_serial 希望这些信息对您有帮助! ### 回答2: 在 Chrome 浏览器中,我们可以使用 JavaScript 关闭串口连接。下面是一种常用的方法: 首先,我们需要使用 `navigator.serial` 对象来获取所有已连接的串口设备。通过调用 `navigator.serial.getPorts()` 方法,我们可以获取一个 `Port` 对象的数组,其中包含所有已连接的串口设备。 接下来,我们可以遍历这个数组,针对每个串口设备调用 `Port.close()` 方法来关闭连接。`Port.close()` 方法会关闭串口连接,并且释放相的资源。 以下是一个简单的示例代码: ```javascript async function closeSerialPorts() { // 获取所有已连接的串口设备 const ports = await navigator.serial.getPorts(); // 遍历所有串口设备,关闭连接 for (const port of ports) { try { await port.close(); console.log(`已关闭串口设备:${port.name}`); } catch (error) { console.error(`关闭串口设备失败:${error.message}`); } } } // 调用上述方法来关闭所有串口连接 closeSerialPorts(); ``` 请注意,这段代码依赖于 Web Serial API,因此只能在支持该 API 的 Chrome 浏览器中运行。另外,由于涉及到对硬件设备的访问,代码可能需要在符合安全性要求的环境下运行,例如通过 HTTPS 或本地开发环境。 希望以上内容对您有帮助! ### 回答3: 要在 Chrome 上使用 JavaScript 关闭串口连接,需要使用 Web Serial API。这个 API 允许 JavaScript 在浏览器中访问串口设备。首先,将串口连接设置为一个变量,然后通过调用 `port.close()` 方法来关闭连接。以下是一个简单的示例代码: ```javascript let port; // 串口连接变量 // 打开串口连接 async function connectSerialPort() { try { port = await navigator.serial.requestPort(); console.log('串口连接成功', port); } catch (error) { console.error('串口连接失败', error); } } // 关闭串口连接 function closeSerialPort() { if (port) { port.close() // 关闭串口连接 .then(() => { console.log('串口连接已关闭'); }) .catch((error) => { console.error('关闭串口连接失败', error); }); } } ``` 在这个例子中,`connectSerialPort` 函数用于打开串口连接,`closeSerialPort` 函数用于关闭串口连接。当调用 `closeSerialPort` 函数时,它会检查是否存在打开的串口连接,并通过调用 `port.close()` 方法来关闭连接。 需要注意,Web Serial API 目前仅在 Chrome 浏览器中可用,并且需要在网页中通过 HTTPS 来使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值