C#学习笔记之使用线程使用
1.背景:
在按键按下的事件回调函数里面发送一条指令,要等待COM口接受数据回调函数完成数据接收后,再发其他指令,显然这是不现实的,经实验不能在按键按下的事件回调函数里面执行死等COM数据接收完成,需要快进快出;故而通过ChatCPT,知道了使用线程的方法来处理COM接收的数据;
2.线程处理接收数据的实例
如下代码是我们根据chatGPT的建议修改的代码:
2.1数据处理线程创建
public partial class MainForm : Form, IView
{
private ManualResetEvent dataProcessedEvent = new ManualResetEvent(false);
// 数据处理线程
private Thread dataProcessingThread;
private bool isRunning = true;
public MainForm()
{
InitializeComponent();
InitializeCOMCombox();
// 启动数据处理线程
dataProcessingThread = new Thread(DataProcessingLoop);
dataProcessingThread.Start();
}
// 窗体关闭事件处理程序
protected override void OnFormClosing(FormClosingEventArgs e)
{
// 停止数据处理线程
isRunning = false;
dataProcessedEvent.Set(); // 解除线程等待状态
dataProcessingThread.Join();
base.OnFormClosing(e);
}
}
2.2 COM数据缓存到ComRecBuffer
public void ComReceiveDataEvent(Object sender, SerialPortEventArgs e)
{
if (this.InvokeRequired)
{
try
{
Invoke(new Action<Object, SerialPortEventArgs>(ComReceiveDataEvent), sender, e);
}
catch (System.Exception)
{
//disable form destroy exception
}
return;
}
// 检查帧头是否为0xAA 0xBB
if ((e.receivedBytes[0] == 0xAA) && (e.receivedBytes[1] == 0xBB)) // 帧头
{
// 检查接收长度是否与预期长度匹配
if (e.receivedBytes[2] == e.receivedBytes.Length) // 接收长度是否完整
{
// 计算接收到数据的CRC16校验值
int iCRC_Value = GetCRC16_CCITT(e.receivedBytes, e.receivedBytes.Length - 2);
// 从接收数据的最后两个字节提取CRC值
int iTemp = e.receivedBytes[e.receivedBytes.Length - 2] << 8;
iTemp |= e.receivedBytes[e.receivedBytes.Length - 1];
// 将计算出的CRC与接收到的CRC进行比较
if (iCRC_Value == iTemp) // CRC16校验
{
// 如果CRC匹配,则将数据复制到最终缓冲区
Array.Copy(e.receivedBytes, 5, ComRecBuffer, 0, e.receivedBytes.Length - 7);
// 触发数据处理完成事件
dataProcessedEvent.Set();
}
}
}
}
2.3 线程里面处理数据和指令发送
// 数据处理循环
private void DataProcessingLoop()
{
byte Status = 0;
while (isRunning)
{
dataProcessedEvent.WaitOne();
UInt16 cmd = (UInt16)((ComRecBuffer[0] << 8) + ComRecBuffer[1]);
switch (cmd)
{
case 0x0070:
if (ComRecBuffer[2] == 0x55)//NAK
{
byte[] bSendBuf = { 0 };
if (Status == 0)
{
//First NAK
SendSerialData((byte)Command_t.ReadBlock, 0x70, 2, bSendBuf, controller);
Status = 1;
}
else if (Status == 1)
{
//second NAK
Status = 0;
SendSerialData((byte)Command_t.ReadBlock, 0xF0, 10, bSendBuf, controller);
}
}
break;
case 0x00F0:
MessageBox.Show("Flash Update Mode!");
Status = 0;
break;
default: break;
}
Array.Clear(ComRecBuffer, 0, ComRecBuffer.Length);
}
}