zw_7627 发表于 2019-5-4 00:35:15

C#两个线程同时接收数据,为什么在listbox里的数据有停顿

只开一个线程的话,就没有显示卡顿的现象。

zyqcome 发表于 2019-5-4 06:34:03

是死循环线程吗?数据量大吗?

mcu5i51 发表于 2019-5-4 08:10:30

用缓冲呀,是不是两个都往列表里写东西等待解锁

liangerfan 发表于 2019-5-4 08:26:51

ui线程控件要用委托啊

zhd1021 发表于 2019-5-4 14:50:17

跨线程操作控件本身是不被允许的,属于线程不安全,但一般懒人都喜欢直接把这个限制用一句话关掉。正确的做法应该用委托,或者自己设置上锁

Error.Dan 发表于 2019-5-4 15:24:55

特别大量或者频繁的UI数据更新本身就不太好处理,特别是在WinForm框架下,它本质还是windows窗口消息机制那一套。
一般写起来最顺手的就是invoke到UI线程上,但是如果你这个委托里面干的事情太多了,或者频繁的去跟窗口线程要执行权,必然会影响UI线程里面其他人,毕竟UI线程只有一个。
数据量大的问题倒还好,关键是有个频繁去要执行权的问题,因为很多时候写着写着发现,我这里要更新一下UI,那里需要更新一下UI,太多了就是问题了。

我推荐的方式是所有的重活全部另外开线程或者起task去后台干,数据更新到UI的缓存里面,.NET框架内置了那么多好用的数据结构,随手都可以捡一个起来用。这里可能存在线程安全问题,但是一般用于显示的数据都不是关键性的,而且采用基于线程安全的数据容器来干的话,可以确保数据不错,顶多就是有部分延迟和更新的次序上有问题,但是这个延迟在面向人眼睛的时候是根本看不出来的。
然后刷界面的事情,让界面自己去干去,我都是起一个Form里面的Timer定期去刷这个缓存,有内容就更新,没有就拉到。

手头正在干的项目后台最多的时候有20多个子进程在做数据收集,本机的网络带宽占用超过2Mbps,我用一个封装了显示元素Class的Queue做缓存,一秒钟刷10次UI(数据收集的周期是100ms,更快问题也不大,但是这个100ms是不准确的),效果我觉得还行~关键是这个方案代码量小到不行,十分钟就可以码完。

zw_7627 发表于 2019-5-4 22:35:48

zyqcome 发表于 2019-5-4 06:34
是死循环线程吗?数据量大吗?

是接收到有效数据后,就死循环显示。数据量比较大。不过我现在放一个线程了。卡顿问题暂时没有了。

zw_7627 发表于 2019-5-4 22:37:15

mcu5i51 发表于 2019-5-4 08:10
用缓冲呀,是不是两个都往列表里写东西等待解锁

FIFO吗?有没有例子呀?

zw_7627 发表于 2019-5-4 22:38:25

liangerfan 发表于 2019-5-4 08:26
ui线程控件要用委托啊

谢谢,我查下委托的用法。

zw_7627 发表于 2019-5-4 22:38:58

zhd1021 发表于 2019-5-4 14:50
跨线程操作控件本身是不被允许的,属于线程不安全,但一般懒人都喜欢直接把这个限制用一句话关掉。正确的做 ...

难怪,前面都要加unsafe。。。

zw_7627 发表于 2019-5-4 22:42:17

Error.Dan 发表于 2019-5-4 15:24
特别大量或者频繁的UI数据更新本身就不太好处理,特别是在WinForm框架下,它本质还是windows窗口消息机制那 ...

谢谢提示{:handshake:} 。“.NET框架内置了那么多好用的数据结构,随手都可以捡一个起来用”,请推荐一个,谢谢。

mcu5i51 发表于 2019-5-5 14:27:42

zw_7627 发表于 2019-5-4 22:37
FIFO吗?有没有例子呀?

没有,也算不上FIFO,两个线程采集数据 之后,保存在一个缓冲中,如果数据量不大也可以处理一下,数据量很大就在单独的线程中处理所有的输入数据,结果同样在一个缓冲中,这里的结果就是对应显示的了,可以是图片或好处理的数据,最后UI中用一定的帧率显示就好了
页: [1]
查看完整版本: C#两个线程同时接收数据,为什么在listbox里的数据有停顿