我目前正在为.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
更改为其他引用类型,但不起作用。非常感谢任何帮助。
除了 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
来测试这一点。 完整代码