求解 c# SerialPort 接收老是要过很久才能收到
程序如下,电脑发下去之后,设备马上有返回,但是我的接收事件要等很久才能收到,高手指点
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Threading;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
SerialPort SP1 = new SerialPort();
List<string> xieyi = new List<string>();
public Form1()
{
InitializeComponent();
SP1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
}
private void Form1_Load(object sender, EventArgs e)
{
string rdline;
int i;
comboBox1.SelectedItem=comboBox1.Items[0];
comboBox2.SelectedItem = comboBox2.Items[0];
try
{
FileStream sFile = new FileStream(".\\d645.txt", FileMode.Open);
StreamReader sr = new StreamReader(sFile);
rdline = sr.ReadLine();
while(rdline!=null)
{
xieyi.Add(rdline);
rdline = sr.ReadLine();
}
label1.Text = xieyi[0];
for (i=1;i<xieyi.Count;i++)
{
checkedListBox1.Items.Add(xieyi[i].Substring(0,4));
checkedListBox1.SetItemChecked(i-1, true);
}
}
catch (Exception ee)
{
MessageBox.Show("加载文件失败:"+ee);
}
}
private void button1_Click(object sender, EventArgs e)
{
try
{
SP1.PortName = comboBox1.SelectedItem.ToString();
SP1.BaudRate = Convert.ToInt32(comboBox2.SelectedItem.ToString());
SP1.Parity = Parity.Even;
SP1.ReceivedBytesThreshold = 1;
SP1.Open();
}
catch (Exception ee) { MessageBox.Show(comboBox1.SelectedItem.ToString() + "失败:"+ee); }
}
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
private void label2_Click(object sender, EventArgs e)
{
}
private void button2_Click_1(object sender, EventArgs e)
{
int i=0;
while (checkedListBox1.GetItemChecked(i))
{
string s = xieyi[i+1];
int len = s.Length / 2;
byte[] bytes = new byte[len];
for (int j = 0; j < len; j++)
{
bytes[j] = Convert.ToByte((s.Substring(j * 2, 2)), 16);
}
try
{
SP1.Write(bytes, 0, len);
}
catch (Exception ee) { MessageBox.Show(comboBox1.SelectedItem.ToString() + "失败:" + ee); }
Thread.Sleep(1000);
richTextBox1.Text += "\r\n";
i++;
if (i >= checkedListBox1.Items.Count)
break;
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string tmpstr = "";
for (int i = 0; i < SP1.BytesToRead; i++)
{
tmpstr += Convert.ToString(SP1.ReadByte(), 16) + " ";
}
safeAddtrText(tmpstr);
}
public delegate void _SafeAddtrTextCall(string text);
private void safeAddtrText(string text)
{
if (this.InvokeRequired)
{
_SafeAddtrTextCall call =
delegate(string s)
{
richTextBox1.Text += s;
};
this.Invoke(call, text);
}
else
{
richTextBox1.Text += text;
}
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
[解决办法]
1。检查波特率、奇偶校验等两边是否一致。
2。DataReceived方法越快越好(慢的话会导致缓冲区中的待读数据越来越多,最后溢出),所以最好把Invoke改成BeginInvoke,防止长时间同步等待UI线程更新界面。
3。DataReceived中的for循环:for (int i = 0; i < SP1.BytesToRead; i++),应把SP1.BytesToRead提到循环外:int bytesToRead = SP1.BytesToRead; 这样缓冲区中有多个数据时才能正确执行。
4。发送过程中不要用Thread.Sleep(1000); 这样会阻塞UI线程(当此时有接收数据到达,会因为要更新界面而被迫等待1秒),改成循环Application.DoEvents(); 并在循环中判断等待的时间是否超过1秒。
[解决办法]
string tmpstr = ""; for (int i = 0; i < SP1.BytesToRead; i++) { tmpstr += Convert.ToString(SP1.ReadByte(), 16) + " "; }
[解决办法]
private void comPort_DataReceiveed(object sender, SerialDataReceivedEventArgs e) { if (bClosing) { return; } try { bListening = true; int n = comPort.BytesToRead; byte[] receiveByte = new byte[n]; comPort.Read(receiveByte, 0, n); AddItemToListBox(receiveByte); ReceiveCount += n; ChangStatus("接收成功!"); } finally { bListening = false; } }
[解决办法]
在for循环中,SP1.BytesToRead是不断变化的,每次调用ReadByte(),BytesToRead就会减1,
所以如果缓冲区有2个以上数据的时候,你的循环方式就读不到后面的数据。
byte[] readBuffer = new byte[SP.BytesToRead];
int byteLength = SP.Read(readBuffer, 0, SP.BytesToRead);
tmpstr = BitConverter.ToString(readBuffer).Replace('-', ' ');
[解决办法]
tmpstr = readBuffer.Aggregate("", (s, b) => s+b.ToString("x")+ ' ');