111,098
社区成员




private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) //接收中断事件
{
System.Threading.Thread.Sleep(100); //延时100ms,等待缓冲区被写入数据
//this.Invoke是跨线程访问UI的方法
this.Invoke((EventHandler)(delegate
{
//检验数据格式
if (radioButton_disHEX.Checked)
{
isDisHEX = true;
isDisASCII = false;
}
else if (radioButton_disASCII.Checked)
{
isDisHEX = false;
isDisASCII = true;
}
if (isDisHEX == false || isDisASCII == true) //以ASCII方式处理数据
{
richTextBox_Receive.SelectionColor = Color.Red;
richTextBox_Receive.AppendText( "<Recv>: " + serialPort.ReadLine() + "\r\n");//以ASCII方式显示数据
}
else //以HEX方式处理数据
{
Byte[] recvStr = new Byte[serialPort.BytesToRead]; //recvStr用于接收字节数据
float[] recvF = new float[serialPort.BytesToRead];
serialPort.Read(recvStr, 0, recvStr.Length);
string recvStrText = null; //声明数组存储接收数据
for (int i = 0; i < recvStr.Length - 1; i++)
{
recvF[i] = Convert.ToSingle(recvStr[i]);
//recvStrText += ("0x" + recvStr[i].ToString("X2") + " ");
}
for (int i = 0; i < recvStr.Length - 1; i++)
{
recvStrText += (recvF[i].ToString() + " ");
}
richTextBox_Receive.SelectionColor = Color.Red;
richTextBox_Receive.AppendText( "<Recv>: " + recvStrText + "\r\n" );
}
serialPort.DiscardInBuffer();//清空缓冲区
}
));
}
Byte[] recvStr = new Byte[serialPort.BytesToRead]; //recvStr用于接收字节数据
int len = serialPort.Read(recvStr, 0, recvStr.Length);
的语句就行了,然后剩下的解析 recevStr 中 len 个长度的字节、业务处理(例如显示到界面上)都应该异步、子线程去执行。这样就及时释放了串口 I/O,可以立刻处理下一组消息,而不会阻塞你的底层设备。
并且上述异步处理中只有“界面到显示”部分才需要 Control.BeginInvoke 语句(注册到主线程去执行),而消息解析和其它数据处理部分不需要在主线程执行,既不阻塞串口I/O也不阻塞主线程渲染。
没有必要使用 float[ ] 时,不要滥用它。此时最多使用 int[ ] 就够了。
如果频繁(循环)使用字符串拼接,那么你应该考虑 StringBuilder 来连接字符内容,而不是滥用拼接字符串。
你的最后的“清空缓冲区”这里是多余的,而且可能也会造成数据丢失。好的应该是写的很少,多余写代码一定是不好的。
System.Threading.Thread.Sleep(10); //延时50ms,等待缓冲区被写入数据
this.Invoke((EventHandler)(delegate
{
string recvStr = serialPort.ReadLine(); //recvStr用于接收字节数据
string[] temp = new string[11] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" };
temp = recvStr.Split('#');
FrameAcquaint( temp, ref Statue);
serialPort.DiscardInBuffer(); //清空缓冲区
}
));
这里的代码根本不应这样写,
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) //串口接收事件(等待重写)
{
这里只能放不阻塞线程的代码
int len=serialPort. BytesToRead];
byte[] readbuf=new byte[len];
serialPort.Read(readbuf,0,len)
buffer.Enqueue(readbuf) <---放到缓冲区里面去,
}
然后自己再启另一线程从缓冲区里取数据接下来怎么干都成
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) //串口接收事件(等待重写)
{
System.Threading.Thread.Sleep(10); //延时50ms,等待缓冲区被写入数据
string recvStr = serialPort.ReadLine(); //recvStr用于接收字节数据
string[] temp = new string[11] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" };
temp = recvStr.Split('#');
FrameAcquaint(temp, ref Statue);
serialPort.DiscardInBuffer(); //清空缓冲区
}
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) //串口接收事件(等待重写)
{
System.Threading.Thread.Sleep(10); //延时50ms,等待缓冲区被写入数据
this.Invoke((EventHandler)(delegate
{
string recvStr = serialPort.ReadLine(); //recvStr用于接收字节数据
string[] temp = new string[11] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" };
temp = recvStr.Split('#');
FrameAcquaint( temp, ref Statue);
serialPort.DiscardInBuffer(); //清空缓冲区
}
));
}
//设置超时读取时间
serialPort.ReadTimeout = -1;
//缓冲区有数据时(即触发接收时间)
serialPort.ReceivedBytesThreshold = 100;
serialPort.ReadBufferSize = 4096;
这样写的委托和非委托方式性能在我PC上没有多少差距,FrameAcquaint只是10个数据的赋值操作。而且SP类性能低下似乎在网上有很多讨论,不是一家之言。我主要的问题是,有没有不通过SP类写串口的方法?除了用WinAPI类库,可不可以在.NET下用QT的dll写?或者有没有其他的高性能串口库?