c#串口程序界面卡死问题

SuperYzz 2017-09-11 09:53:16
private void sp_DataReceived(object sender,SerialDataReceivedEventArgs e)
{
System.Threading.Thread.Sleep(100); //延时100ms等待接收完数据
//this.Invoke就是跨线程访问ui的方法
this.Invoke((EventHandler)(delegate
{
if (isHex == false)
{
tbxRecvData.Text += sp.ReadLine();
}
else
{
Byte[] ReceivedData = new Byte[sp.BytesToRead]; //创建接收字符数组
sp.Read(ReceivedData, 0, ReceivedData.Length);
String RecvDataText = null;
for (int i = 0; i < ReceivedData.Length - 1; i++)
{
RecvDataText += ("0x" + ReceivedData[i].ToString("X2") + "");
}
tbxRecvData.Text += RecvDataText;
}
sp.DiscardInBuffer(); //丢弃接收缓冲区数据
}));
}

好像是这段代码哪里的问题导致界面卡死
大佬们看一下帮忙改一下
...全文
1768 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
无情时尚 2017-09-12
  • 打赏
  • 举报
回复
简单编写测试,没有问题,可以正常发送接收



using System;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;

namespace COMTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private SerialPort sp = new SerialPort();

private void btnOpen_Click(object sender, EventArgs e)
{
sp.PortName = "COM2";
sp.BaudRate = 9600;
sp.DataBits = 8;
sp.StopBits = StopBits.One;
sp.Parity = Parity.None;
sp.ReadTimeout = 1000;
sp.ReceivedBytesThreshold = 1;
if (!sp.IsOpen)
sp.Open();

sp.DataReceived += Sp_DataReceived;
btnOpen.Enabled = false;
}

private void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] data = new byte[sp.BytesToRead];
sp.Read(data, 0, data.Length);
sp.DiscardInBuffer();
UpdateTextBox(texRev, Encoding.Default.GetString(data));
}

private void btnSend_Click(object sender, EventArgs e)
{
byte[] data = Encoding.Default.GetBytes(texData.Text);
sp.Write(data, 0, data.Length);
}
private void UpdateTextBox(TextBox sender, string content)
{
this.Invoke((EventHandler) delegate
{
sender.AppendText(content + Environment.NewLine);
});
}
}
}
无情时尚 2017-09-12
  • 打赏
  • 举报
回复
        private void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] data = new byte[sp.BytesToRead];
            sp.Read(data, 0, data.Length);
            sp.DiscardInBuffer();
            UpdateTextBox(texRev, Encoding.Default.GetString(data));
        }

 private void UpdateTextBox(TextBox sender, string content)
        {
            this.Invoke((EventHandler) delegate
            {
                sender.AppendText(content + ++num + Environment.NewLine);
            });
        }
exception92 2017-09-12
  • 打赏
  • 举报
回复
依据什么判断定100ms 数据接收完毕?使用this.invoke 可以,因为DataReceived 由其它线程执行,而textbox创建隶属UI线程。 不要用sleep,而应该尽可能的在“处理接收数据”上下功夫,也就是接收的数据不应该用sleep 来堆积到缓冲区,而是由程序来进行顺序处理,使用线程安全的ConcurrentQueue来接收并处理数据。
cyg17173 2017-09-12
  • 打赏
  • 举报
回复
System.Threading.Thread.Sleep(100); //延时100ms等待接收完数据 这句要少用。 我说下我的思路: DataReceived 这个方法之外应该有一个变量去储存每时每刻获取到的下位机数据。 监视该变量,委托+事件去处理数据。 最后,数据处理完毕Invoke 匿名委托去填充窗体控件。 说的不对请参考。
SuperYzz 2017-09-12
  • 打赏
  • 举报
回复
我使用BeginInvoke,还是要卡死,我该怎么改了这段代码呢
  • 打赏
  • 举报
回复 2
例如像 RecvDataText += ("0x" + ReceivedData[i].ToString("X2") + ""); 这种代码,以及前边几行代码,根本不操作UI 控件,那么根本不应该放到 Invoke 中。而且只是一般地临时显示的话,使用 BeginInvoke 显然比 Invoke 更好。 你在阻塞 UI 线程(Invoke它)的时候,你执行 sp.ReadLine(); 这样的代码,这个 ReadLine 本身就是卡死、死等、阻塞式的代码,要等待对方传来换行回车或者文件结束符号才能解除阻塞。显然这样编程设计是不合适的。 尤其是通讯程序,要处理粘包、分包概念,更不应该阻塞式 Readline。

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧