【问题标题】:C# Com port closeC# Com 端口关闭
【发布时间】:2017-03-05 20:37:02
【问题描述】:

我需要从COM 中读取Form1 中的数据,然后还要再次在Form2 中读取数据。

最好的方法是什么?

Form1 中读取COM 数据,然后在mySerialPort.Close(); 中,在Form2 中打开新连接?
如果是这样,我应该在上面的代码中的哪个位置 close 呢?

还是不要关闭COM?如果不关闭,如何读取Form2中的数据?

namespace portreader
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            SerialPort mySerialPort = new SerialPort();
            mySerialPort.PortName = "COM3";
            mySerialPort.BaudRate = 9600;
            mySerialPort.Parity = Parity.None;
            mySerialPort.StopBits = StopBits.One;
            mySerialPort.DataBits = 8;
            mySerialPort.Handshake = Handshake.None;
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_DataReceived);
            mySerialPort.Open();
        }

        string _buffer;
        private void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (this.InvokeRequired)
            {
                // Using this.Invoke causes deadlock when closing serial port, and BeginInvoke is good practice anyway.
                this.BeginInvoke(new EventHandler<SerialDataReceivedEventArgs>(mySerialPort_DataReceived), new object[] { sender, e });
                return;
            }
            SerialPort sp = (SerialPort)sender;
            string data = sp.ReadExisting();

            _buffer += data;
            if (_buffer.Length >= 8)
            {
                int chipnumber = Int32.Parse(_buffer, System.Globalization.NumberStyles.HexNumber);
                Form2 form2 = new Form2(chipnumber);
                form2.ShowDialog(this);
                _buffer = null;
            }
        }
    }
}

【问题讨论】:

  • 就个人而言,我会创建一个专门处理应用程序的通信端口通信的类,并让两种形式都使用它。

标签: c# winforms


【解决方案1】:

你需要创建一个 form1 和 form2 都可以使用的类,然后给 form1 和 form2 一个对该类的引用。

理想情况下,表单根本不知道有串行端口。他们只是使用您的类/服务来提出问题并获得答案,并且封装在该类中的是转到串行端口并进行查询的逻辑。

这是软件的基本设计原则之一,将您的 UI 与应用程序逻辑分开。

在另一篇相关帖子中查看我的回答

Serial Port Polling and Data handling

【讨论】:

    【解决方案2】:

    你可以简单地将ComPort 包装在一个类中

    public class DataInput
    {
        public event Action<string> DataReceived;
    
        private readonly SerialPort mySerialPort;
    
        public DataInput(string portName)
        {
            mySerialPort = new SerialPort();
            mySerialPort.PortName = portName;
            mySerialPort.BaudRate = 9600;
            mySerialPort.Parity = Parity.None;
            mySerialPort.StopBits = StopBits.One;
            mySerialPort.DataBits = 8;
            mySerialPort.Handshake = Handshake.None;
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_DataReceived);
            mySerialPort.Open();
        }
    
        private void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string received = mySerialPort.ReadExisting();
            DataReceived?.Invoke(received);
        }
    }
    

    现在每个表单(以及您软件的其他组件)都可以订阅DataInput 实例的事件DataReceived。所以每个组件都可以按照自己喜欢的方式处理数据。因此,您只需创建一个 DataReceived 的实例并在您的表单中使用它,例如:

    public partial class Form1 : Form
    {
        private readonly DataInput dataInput;
    
        public Form1()
        {
            InitializeComponent();
            dataInput = new DataInput("COM3");
            dataInput.dataReceived += OnDataReceived;
        }
    
        private void OnDataReceived(string Data)
        {
            //Do whatever you want with the data
        }
    }
    

    现在您可以将dataInput 传递给您的第二个表单,您可以再次使用dataReceived 事件。

    【讨论】:

    • 我是 c# 新手,想问你是否可以告诉我如何在表单中使用 DataReceived 并最终得到它:_buffer += DataReceived;
    • 我在答案中添加了一个示例 - 希望这会有所帮助!
    猜你喜欢
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 2018-06-17
    相关资源
    最近更新 更多