用C#控件写串口调试助手,关闭串口时程序锁死

bug现象:打开串口时正常,再切换到关闭串按钮口后,按下按钮要等待很久的时间才能恢复到正常的界面,这其中按任何一个按钮都没用。
参考博客:https://blog.csdn.net/wuyazhe/article/details/5606276
解决方案:首先我们先来整理一下思路,搞清楚整个的工作流程,串口调试的上位机主要由两部分控制,一个是UI进程一个串口监视进程(优先级别高),UI进程主要是通过消息循环来控制整个的功能实现,在读数据阶段,若果此时要关闭串口,那就很尴尬了,一般的工作流程都是等待数据传送完成之后,执行invoke调用UI线程,更新界面,才能结束监视进程,这就让两个线程都一直卡在Invoke这个地方,所以这个地方就需要用到Application.DoEvents()(消息循环),提前的结束循环,但还是有问题,因为监控进程的优先级别比较高,还是会卡住,所以在程序里面就需要对异常状态进行捕获,具体代码如下:
void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (Closing) return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环
try
{
Listening = true;//设置标记,说明我已经开始处理数据,一会儿要使用系统UI的。
int n = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
received_count += n;//增加接收计数
comm.Read(buf, 0, n);//读取缓冲数据
builder.Clear();//清除字符串构造器的内容
//因为要访问ui资源,所以需要使用invoke方式同步ui。
this.Invoke((EventHandler)(delegate
{
//判断是否是显示为16禁止
if (checkBoxHexView.Checked)
{
//依次的拼接出16进制字符串
foreach (byte b in buf)
{
builder.Append(b.ToString(“X2”) + " ");
}
}
else
{
//直接按ASCII规则转换成字符串
builder.Append(Encoding.ASCII.GetString(buf));
}
//追加的形式添加到文本框末端,并滚动到最后。
this.txGet.AppendText(builder.ToString());
//修改接收计数
labelGetCount.Text = “Get:” + received_count.ToString();
}));
}
finally
{
Listening = false;//我用完了,ui可以关闭串口了。
}
}
private void buttonOpenClose_Click(object sender, EventArgs e)
{
//根据当前串口对象,来判断操作
if (comm.IsOpen)
{
Closing = true;
while (Listening) Application.DoEvents();
//打开时点击,则关闭串口
comm.Close();
Closing = false;
}
else
{
//关闭时点击,则设置好端口,波特率后打开
comm.PortName = comboPortName.Text;
comm.BaudRate = int.Parse(comboBaudrate.Text);
try
{
comm.Open();
}
catch(Exception ex)
{
//捕获到异常信息,创建一个新的comm对象,之前的不能用了。
comm = new SerialPort();
//现实异常信息给客户。
MessageBox.Show(ex.Message);
}
}
//设置按钮的状态
buttonOpenClose.Text = comm.IsOpen ? “Close” : “Open”;
buttonSend.Enabled = comm.IsOpen;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用C#串口调试助手的基本代码: ``` using System; using System.IO.Ports; using System.Windows.Forms; namespace SerialPortAssistant { public partial class MainForm : Form { private SerialPort serialPort; public MainForm() { InitializeComponent(); serialPort = new SerialPort(); serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived); } private void MainForm_Load(object sender, EventArgs e) { string[] portNames = SerialPort.GetPortNames(); foreach (string portName in portNames) { comboBoxPortName.Items.Add(portName); } if (portNames.Length > 0) { comboBoxPortName.SelectedIndex = 0; } } private void buttonOpen_Click(object sender, EventArgs e) { if (serialPort.IsOpen) { serialPort.Close(); } serialPort.PortName = comboBoxPortName.SelectedItem.ToString(); serialPort.BaudRate = int.Parse(comboBoxBaudRate.SelectedItem.ToString()); serialPort.Parity = (Parity)Enum.Parse(typeof(Parity), comboBoxParity.SelectedItem.ToString()); serialPort.DataBits = int.Parse(comboBoxDataBits.SelectedItem.ToString()); serialPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), comboBoxStopBits.SelectedItem.ToString()); serialPort.Open(); buttonOpen.Enabled = false; buttonClose.Enabled = true; } private void buttonClose_Click(object sender, EventArgs e) { if (serialPort.IsOpen) { serialPort.Close(); } buttonOpen.Enabled = true; buttonClose.Enabled = false; } private void buttonSend_Click(object sender, EventArgs e) { if (serialPort.IsOpen) { string data = textBoxSend.Text; serialPort.Write(data); } } private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { string data = serialPort.ReadExisting(); this.Invoke(new Action(() => { textBoxReceive.AppendText(data); })); } } } ``` 此程序包括以下功能: 1. 打开和关闭串口 2. 发送数据到串口 3. 接收串口数据并显示在文本框中 你可以通过添加其他控件和功能来扩展它,例如: 1. 添加一个清除接收文本框的按钮 2. 显示串口的状态(开启/关闭) 3. 添加错误处理和异常处理 4. 支持不同的编码格式(例如UTF-8,ASCII等) 5. 支持自定义串口设置 6. 添加一个日志记录功能 7. 等等 以上仅为基本代码,您可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值