我的程序和一台医疗仪器通讯。通讯建立后,该医疗仪器每次发送一行数据(但我也不确定一行数据是分次发还是一次性发,因为这个程序不是我写的,但从结果上判断,应该是一次性发送的)。结果我的程序一般情况下先收200字节,然后再收48字节(偶尔也会一次性收248字节,所以我判断医疗仪器是一次性发送一行数据)。
我的程序是在ReveiveData事件中接收数据的,另外,ReceivedBytesThreshold属性设置为1。我的程序已经依靠数据侦的首尾标志解决分段接收的问题,但以下疑问在心中,仍无法得到答案 但为什么我的程序是先收200字节,再收48字节?我的ReadBufferSize已经设置为1M了,为何没有效果?还请高手解答。
另:还有没有其它数据接收方式,能够一次性接收完对方一次性发送过来的数据?
我的程序是在ReveiveData事件中接收数据的,另外,ReceivedBytesThreshold属性设置为1。我的程序已经依靠数据侦的首尾标志解决分段接收的问题,但以下疑问在心中,仍无法得到答案 但为什么我的程序是先收200字节,再收48字节?我的ReadBufferSize已经设置为1M了,为何没有效果?还请高手解答。
另:还有没有其它数据接收方式,能够一次性接收完对方一次性发送过来的数据?
解决方案 »
- c#可以调用DLL里头的函数,能不能调用exe文件里头的函数呢?
- 请教大家,如何简便地从一个字符串中取出所有的数字,例如输入“ab12cd34", 输出”1234“, 如果用正则表达式怎么实现呢?
- 当鼠标划过gridview的行时,该行的字体能够变色,因为是超链接列,所以还要显示下划线,当鼠标离开是字体颜色恢复并看不见下划线,请大家
- 关于日期的问题,已有一个日期2006-04-15,如何得出30天后的日期
- 能返回值的对话框?
- cs类文件中不能用缓存是怎么回事
- C#程序发布问题!!
- 紧急求救,望好心人帮忙,谢谢!!!!
- datagrid讨论(附原码),高手请进
- 问个问题!!!
- winform导出Execel问题帮看一下了
- 关于敏捷开发中如何处理数据库的解决方法
我在接收事件里用byte[] data=new int[208];
for (int i = 0; i < 208; i++)
{
data[i] = Convert.ToByte(serialPort1.ReadByte());
}
处理完之后再用serialport1.discadinbuffer();
你把他设置成200看看……
selMonitor.Read(data, 0, data.Length);如果你不设置一次读取的大小,程序会一次完整把缓存里的数据全部提走.
上面的就可以.(尽量用线程来读)
现在最关键的是,我总怀疑上位机是一次性发了一条数据(约300-500字节),而我的程序却分了N次接收后再合并的。现在有没有方法能够做到对方发送一条数据,而我这边也仅只要收一次。ReadExisting()方法不能用,因为它返回字符串,而我的数据还需要分析二进制后再解码的。有兄弟说用sleep,不知道能不能行,还没试。 protected void ReceiveBySubsection()
{
byte[] readBuffer = new byte[BUFFERSIZE];
//关键就在此方法上,是不是read方法不能一次性把缓冲区中的所有数据都读完?
//我也怀疑是ReceivedBytesThreshold=1导致频繁激发Receive事件,但仅是怀疑
int count = sp.Read(readBuffer, 0, readBuffer.Length); //接收到新数据,清空原有数据,StartWithFlag为自己编写的方法 if (StartWithFlag(readBuffer))
{
datas = new List<byte>();
}
if (datas == null)
{
OnErrorReceived(new ErrorReceiveEventArgs("一次性分段接收数据出错,未接收到起始标志。", true));
return;
}
//CopyDataToList将数据追加到List集合,是自定义的方法
CopyDataToList(datas, readBuffer, count);
//判断有没有收到结束标志
if (EndWithFlag(readBuffer))
{
//进行下一步的解码和分析数据的操作
DecodeAndAnalyse(datas);
}
}
你可以自己开一个线程来处理就好了,如果发送的命令含有固定的结束符,可以用ReadTo函数,如果没有可以用Read或者ReadExist等等
Thread.Sleep(50);
if (p.BytesToRead > 0)
{
//循环接收
string strData = p.ReadExisting();
}这样试试
技术要点:
(1).首先,SerialPort的ReceivedBytesThreshold先设置成1,表示只要有1个字符送达端口时便触发DataReceived事件
(2).当DataReceived触发时,先把ReceivedBytesThreshold设置成一个比较大的值,达到读取本次端口数据时,不再触发DataReceived.
(3).循环读取端口中的数据,直至读完。
(4).移除读取数据中的非法字符。
(5).触发一个后台线程处理收到的数据。
(6).在finally中把ReceivedBytesThreshold重置回1 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (sender.GetType() != typeof(System.IO.Ports.SerialPort))
{
return;
}
string strReceive = string.Empty;
string strCollect = string.Empty;
System.IO.Ports.SerialPort comPort = (System.IO.Ports.SerialPort)sender; try
{
comPort.ReceivedBytesThreshold = comPort.ReadBufferSize;
while (true)
{
strReceive = comPort.ReadExisting();
if (string.Equals(strReceive, string.Empty))
{
break;
}
else
{
strCollect += strReceive;
Application.DoEvents();
Thread.Sleep(100);
}
}
strCollect = strCollect.Replace("\0", string.Empty);
strCollect = strCollect.Replace("\r\n", string.Empty);
strCollect = strCollect.Replace("\r", string.Empty);
strCollect = strCollect.Replace("\n", string.Empty); if (!this.bIsHandleCom)
{
this.bIsHandleCom = true;
mReceiveData = strCollect;
if (ReceiveDataParserEvent != null)
ReceiveDataParserEvent(mReceiveData);
if (ThreadReceiveParser != null && !ThreadReceiveParser.IsAlive)
{
ThreadReceiveParser.Start();
}
} }
catch (Exception ex)
{
MessageBox.Show(this, ex.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
comPort.ReceivedBytesThreshold = 1;
}
}