日期:2014-05-18  浏览次数:21307 次

C# 数据采集类的应用程序,数据显示的有关问题。
C# WinForm做数据采集类的程序,这种应用广,基本上都是串口通信或者以太网通信之类,功能大概就是上位机软件与硬件进通过协议控制,采集数据,或者控制硬件做什么事情。之前自己一贯的做法是通过注册事件,触发事件调用委托来更新UI,因为这种方法简单,好理解一点,应该算是事件订阅这种模式吧,通信类声明事件,接收数据后触发传递给注册它的事件的UI,然后更新到界面,但是遇到采集大量数据时,就会经常因为更新UI导致接收数据堵死,缓冲区溢出之类的问题,而且一次更新大量数据,频繁更新UI都会导致UI界面卡死。

求助大家是如何处理这类问题的,最好能给例子代码,现在就遇到了用TCP接收远程发来的数据,因为数据量太大(8192个字节一次,频率也很大,基本上就是连着发的),到更新UI的时候,按照以前那种方法,不用多久,客户端界面就卡死了,然后远程服务端也提示缓冲区队列满了,发送失败的问题。

另外想请教大家,TCP通信的时候,发送粘包是怎么处理的;TCP发送数据的是,能不能连续发送大量数据,因为我之前连续的发送大量数据的包,结果在客户端发现丢包了,或者包的个数多了很多,但是在连续发送之间Sleep一下,客户端接收到的数据就完全对了,这是怎么回事。

------解决方案--------------------
开线程,我一般的做法是,接收事件中,将接受的数据放到内存,后台跑线程从内存中拿数据,那一条处理一条,不影响接收
------解决方案--------------------
一般是接收只管接收,处理的只管处理

也就是接收的只管把数据放到内存里,显示的只管去内存里取数据
------解决方案--------------------
内建一个数据缓存放到内存里,要考虑数据处理速度,如果UI更新界面无法实时将内存中数据全部拿走,导致内存中滞留数据越来越多,建议通过算法来将数据进行合并,以便可以一次性将数据全部拿走。或者将数据保存在硬盘。然后再从硬盘中慢慢读取,免得时间长了导致内存溢出。
其他的与2、3楼说的一样。要将接收和界面更新分开。这是设计的问题。
------解决方案--------------------
频繁更新UI:
建议先缓存(不直接更新到UI),当收到的帧达到一定数量时一起更新到UI,或者定时更新到UI.
粘包:
我想这个是这类程序必须处理的一个问题吧?
我之前的做法是将接收到的数据先判断是否包含一个完整的帧(当然帧是可以自解释的),如果有,则截取一个完整的帧,把剩余的数据暂时保存,等待下次接收到数据时,合并后再判断是否包含完整的帧,如此循环。这个办法不是很通用,需要有一定的假设前提。

希望对楼主有用。