怪问题,求高手帮解决!!多线程中丢数据的问题

allen421 2016-04-07 03:50:24
【背景介绍】:本人原来开发了一套多通道数据采集分析系统,分析软件开发环境是VS2010,.Net4.0,使用C#语言编写,配合NI measurement studio2010做图形显示,另外还用了DXPerience10的控件。
多通道采集器通过UDP协议与软件进行数据通讯,软件和采集器有一套完善的通讯协议,通讯过程是这样的,软件发送数据请求包,采集器将所有24通道数据发送给软件(24包)。为保证数据完整性,软件存储策略是收到全部数据后才同意存储,否则丢弃数据,等到下一帧数据。
该软件也开发完成较长时间,软件在【正常笔记本】上运行正常,win7 32位 64位 xp下都没问题。

【遇到的问题】本次想继续升级采集器,在采集器内部集成了一个【工控机模块】,安装了64位Win7,和正常电脑用起来没什么区别,用的是Atom CPU,软件直接在里面运行,可以脱离笔记本采集存储数据。
但是在原有软件和通讯协议未改动的情况下,发现软件在新采集器运行是实时数据显示卡顿,经常三四秒才更新数据(正常通讯是每秒请求一次数据,相应界实时数据显示也是每秒更新),起初怀疑工控机的CPU图形处理能力较差,导致界面不更新,但通过更深入的排查,发现是多线程丢包了。
具体判据如下:
(1)用抓包软件查看网络收发情况,发现通讯流畅不存在网络丢包的情况。
(2)在软件中添加相应代码监测实时数据情况发现,问题是由于负责接收数据的线程丢失数据,导致未收到完整24通道数据,软件存储策略将这一帧的数据丢弃所致。丢失数据的情况比较随机,正常共24包数据,每次丢数据时收到数据从十几包到23包不等。
(3)将线程中等待数据的时间延长,依然无法等到数据,确实是没了,不是迟了。。。

【目前所做的努力】
除上面所说监测代码运行情况抓包等工作外,本想将开发环境包括.net环境升级到更高版本,无奈配合使用NI mesurement Studio新版本的资源比较难找,暂时还没升级。
另外,原软件是在32位环境下开发的,编译成64位后也没啥改观。
【相关代码】
(1)主线程中等待数据代码
while (true)
{
try
{
allData=new byte[ChannelCount][];
receivedCount = 0;
//请求数据
Send(reqBuffer);

CanReceive = true;//开始接收

int waitTime = 0;
bool bOutTime = false;

Thread.Sleep(6);
while (receivedCount <ChannelCount) 收到数据不够24通道就不处理
{
Thread.Sleep(40);
waitTime++;
Debug.WriteLine("等待中" + DateTime.Now.ToString() + "-" + DateTime.Now.Millisecond.ToString() + "waittime" + waitTime);
if (waitTime > 10)
{
bOutTime = true;
break;
}
}
(2)子线程中处理数据部分代码,子线程是在主线程中开启的
public static void ReceiveThreadRun()
{
byte[] receivebytes;
while (true)
{
try
{
if (!CanReceive)
Thread.Sleep(2);

receivebytes = Receive();

while (receivedCount >= allData.Length && CanReceive)
Thread.Sleep(2);
try
{
allData[receivedCount] = receivebytes;
}
catch (Exception ex)
{
}
bool rs = 处理协议数据(receivebytes);
if(rs)
receivedCount++;
(3)子线程(2)中接收数据代码如下
private static byte[] Receive()
{
byte[] re;
MainForm.MaiInstance.网络状态 = Status.Running;
re=udpClient.Receive(ref localEndPoint);//接收数据代码
MainForm.MaiInstance.网络状态 = Status.DarkRunning;
return re;

对代码运行情况的监测最深就带这里,丢数据时监测这里运行情况就收不到数据了

目前就是以上的情况,望各位大神不吝赐教,先谢过了
...全文
815 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
bbwolfcool 2016-04-12
  • 打赏
  • 举报
回复
楼上的那些水货不用看了,直接贴上去抄吧, 监听必须时刻等待对方发送内容,接收线程不能有任何Sleep,处理里面可以有,监听线程你认为正确的Sleep可能这个时候对方发了内容,可能就几十毫秒,即使你Sleep了几毫秒,也会丢数据 http://cn.bing.com/search?q=udp+%E5%BC%82%E6%AD%A5+c%23&go=%E6%8F%90%E4%BA%A4&qs=n&form=QBRE&pq=udp+%E5%BC%82%E6%AD%A5+c%23&sc=0-7&sp=-1&sk=&cvid=A84DCB1E360B473A9ECF6523B64E80B2
bbwolfcool 2016-04-11
  • 打赏
  • 举报
回复
楼上那么多人,竟然讨论那么激烈,一群蠢蛋,当前线程一会Sleep一会正常工作,对方咋知道你这时候是在Sleep还是工作? 必须加异步轮询,还UDP丢包不奇怪。。。。。太无知了
wq1234wq 2016-04-11
  • 打赏
  • 举报
回复
为什么不用异步,while (true) 用信号量控制。
bbwolfcool 2016-04-11
  • 打赏
  • 举报
回复
都是扯淡,谁说UDP就要丢包, 开始接收必须要异步,并且循环,代码里面那么多Sleep,怎么可能正好是非Sleep状态收到数据包,Tcp还是黑 receivebytes = Receive(); 必须改异步,然后在endinvoke里面写结果处理
regainworld 2016-04-10
  • 打赏
  • 举报
回复
4楼说得对,应该开一个死循环线程收udp包,记录接收包数,测试一下会不会丢包。理论上会丢,但在工程实践中,300mbps没问题。不要人云亦云,测试结果说话。
Poopaye 2016-04-07
  • 打赏
  • 举报
回复
引用 6 楼 allen421 的回复:
感谢大家回复,当初考虑到采集器芯片的处理能力,udp效率高点,另外是的单独的局域网,网络环境较好,所以选的udp 之前都很好,就是换这个集成的计算机就不行了 我抓包软件看到数据包已经到达网卡了,但是程序udp接收那里没了,这能完全说是用UDP协议的问题吗?
那是处理不过来了,数据就会丢掉,可以通过增加ReceiveBufferSize来优化 不过不管你怎么弄,udp丢包是必然的
allen421 2016-04-07
  • 打赏
  • 举报
回复
感谢大家回复,当初考虑到采集器芯片的处理能力,udp效率高点,另外是的单独的局域网,网络环境较好,所以选的udp 之前都很好,就是换这个集成的计算机就不行了 我抓包软件看到数据包已经到达网卡了,但是程序udp接收那里没了,这能完全说是用UDP协议的问题吗?
xian_wwq 2016-04-07
  • 打赏
  • 举报
回复
sorry,还以为是tcp,原来是udp,撤回4楼的回复
xian_wwq 2016-04-07
  • 打赏
  • 举报
回复
个人觉得首先应该把数据接收和数据解析分离, 数据接收线程接收数据后把数据放入缓存(或线程安全的容器),然后快速返回, 数据拼包和解析放到另外的线程中去。 否则不是你接收不到,而是处理速度跟不上,表现为数据接收不全。
xuzuning 2016-04-07
  • 打赏
  • 举报
回复
UDP 是无状态协议,只管发送,并不管对方是否收到 所以丢失数据是常态,不丢失是运气
linjiagao052 2016-04-07
  • 打赏
  • 举报
回复
引用 1 楼 shingoscar 的回复:
看到udpClient,问题就解释的通了 你用udp传输,包全丢光也是正常现象,哪里算怪问题 要么换tcp,要么自己做重发机制
的确是
Poopaye 2016-04-07
  • 打赏
  • 举报
回复
看到udpClient,问题就解释的通了 你用udp传输,包全丢光也是正常现象,哪里算怪问题 要么换tcp,要么自己做重发机制

110,561

社区成员

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

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

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