如何从串行端口的静态事件处理程序获取数据

问题描述 投票:0回答:1

我目前正在为.NET框架编写一个用C# winform从串口连续读取数据的方法。

我为它编写了一个事件处理程序,但由于它是静态的,我无法从外部调用变量。 现在我正在考虑如何从静态方法获取数据到外部。就像静态方法和普通方法之间共享数据一样。

Ofc 这将无法正常工作。我想要

sp
变量进入
mySerialPort
但我不知道如何。

private void GetComPortData()
{
    SerialPort mySerialPort = new SerialPort("COM5");
    mySerialPort.BaudRate = 115200;
    mySerialPort.Parity = Parity.None;
    mySerialPort.StopBits = StopBits.One;
    mySerialPort.DataBits = 8;
    mySerialPort.Handshake = Handshake.None;
    mySerialPort.RtsEnable = true; //change to false if not need rts
    mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
    mySerialPort.Open();
    

    //how to make mySerialPort = sp?
    //string dataComPort = mySerialPort.ReadExisting();
    var data = dataComPort.Split(new[] { '/' },4);
    /*Do some work to show data in datagridview*/
    mySerialPort.Close();
}
//handle comport data
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
}

我也尝试将

static
更改为其他引用类型,但不起作用。非常感谢任何帮助。

c# winforms serial-port static-methods eventhandler
1个回答
0
投票

除了 Olivier 关于“不关闭”串行端口的精彩评论之外,还有可能

DataReceived
在不同的线程上。如果您打算“做一些工作以在 datagridview 中显示数据”,您可能必须
BeginInvoke
来防止跨线程异常。我曾经经常做这种事情,下面是一个对我有用的示例,用于接收事件,然后在处理程序循环获取“所有”(可能需要某种限制)数据时锁定关键部分显示块时在缓冲区中可用 <= 16 bytes in the DGV.


设置DataGridView

public partial class MainForm : Form
{
    public MainForm() =>InitializeComponent();
    .
    .
    .
    BindingList<DataReceived> DataSource { get; } = new BindingList<DataReceived>();
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        dataGridView.DataSource = DataSource;
        dataGridView.AllowUserToAddRows = false; // Critical for this example.
        dataGridView.Columns[nameof(DataReceived.Timestamp)].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
        dataGridView.Columns[nameof(DataReceived.Data)].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

        MockSerialPort mySerialPort = new MockSerialPort("COM5");
        mySerialPort.BaudRate = 115200;
        mySerialPort.Parity = Parity.None;
        mySerialPort.StopBits = StopBits.One;
        mySerialPort.DataBits = 8;
        mySerialPort.Handshake = Handshake.None;
        mySerialPort.RtsEnable = true;
        mySerialPort.DataReceived += DataReceivedHandler;
        mySerialPort.Open();
    }
    .
    .
    .

处理接收到的数据

    .
    .
    .
    SemaphoreSlim _criticalSection = new SemaphoreSlim(1, 1);
    private async void DataReceivedHandler(object sender, MockSerialDataReceivedEventArgs e)
    {
        await _criticalSection.WaitAsync();
        if(!IsDisposed) BeginInvoke((MethodInvoker)delegate 
        {
            try
            {
                if (sender is MockSerialPort port)
                {
                    while (port.BytesToRead > 0)
                    {
                        byte[] buffer = new byte[16];
                        int success = port.Read(buffer, 0, buffer.Length);
                        string display = BitConverter.ToString(buffer, 0, success).Replace("-", " ");
                        var data = new DataReceived { Data = display };
                        DataSource.Add(data);
                    }
                }
            }
            finally
            {                    
                _criticalSection.Release();
            }
        });
    }
}

class DataReceived
{
    public string Timestamp { get; } = DateTime.Now.ToString(@"hh\:mm\:ss\.fff tt");
    public string? Data { get; set; }
}

我用

MockSerialPort
来测试这一点。 完整代码

© www.soinside.com 2019 - 2024. All rights reserved.