c# winform 数据实时刷新问题

SomethingJack 2014-10-23 10:26:00
我从雷达上获取数据,雷达的收发时间是实时的,大概50ms收取一次消息,很快速.
有一些相关信息我需要获取过来后,在一个GRID上显示,但是我发现一个问题.就是数据实时更新的时候,比如我点击或者拖动窗体会造成卡顿或者假死的情况.以下是我模拟数据实时刷新的代码.请问我这种情况该如何考虑?使用多线程?还是?以下代码只是模拟,可能会有歧义.

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.Threading;

namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 100000; i++)
{
this.dataGridView1.DataSource = getTable(i);
this.dataGridView1.Refresh();
this.dataGridView1.Update();
}

}

public DataTable getTable(int i)
{
DataTable table = new DataTable();
table.Columns.Add("column1", System.Type.GetType("System.String"));
table.Columns.Add("column2", System.Type.GetType("System.String"));
DataRow row = table.NewRow();
row["column1"] = "AXsasas" + i;
row["column2"] = "AAdasdas" + i;
table.Rows.Add(row);
table.AcceptChanges();
return table;
}

private void Form1_Load(object sender, EventArgs e)
{
//getTable();
//this.dataGridView1.DataSource = getTable();
}
}
}

...全文
20141 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_18835365 2018-08-02
  • 打赏
  • 举报
回复
引用 2 楼 bdmh 的回复:
用线程,把接收到的数据放到list中,不作处理,后台开一个线程对list中的数据循环做处理,处理完了通知UI更新界面


引用 14 楼 github_22161131 的回复:
和之前@Z65443344说的类似,
这个需求,在实现时需要注意两个点:一是程序的运行时间可能比较久,那就不要把数据都放到内存里。二是界面的刷新没必要和和数据的刷新同步,50ms一次更新,界面本来也反应不过来。

你需要一个中间介质保存数据,我建议最好是一个数据库,如果是没有服务器的,可以使用像SQLite或者SQL Server Compact这样的嵌入式数据库。比起自己写文件来,一个好处是帮你实现了线程安全的读写,另一个是方便查询。

然后需要两个缓冲区(可以就是list,最好创建时就固定好大小),开一个线程不断从设备读取数据到缓冲区,在数据到达一定量(这个可以根据系统性能调整)时,切换到另一个缓冲区,同时使用异步方法或另一个线程将之前填满的缓冲区一次性写入数据库。(其实SQLite每秒写20条数据很轻松,可能都不需要缓冲区)

界面上用一个定时器比如1s从缓冲区或者数据库取数据显示到界面,不要一次加载所有数据,可以按需加载,比如默认加载最新的1000条。需要看之前的数据时再加载之前的。


两位大哥,能否帮我解决个问题啊,不胜感激!
https://bbs.csdn.net/topics/392424461?page=1#post-403382629
绝地灬武士 2016-09-06
  • 打赏
  • 举报
回复
引用 4 楼 sp1234 的回复:
首先在业务通讯协议设计方面,我们能够想到的最蠢的方法,可能就是轮询了。假设只有这一种办法得到新数据,那么是悲哀的。 然后就算是如此读取数据,你读取数据跟显示也是两个异步过程,设计到一个同步过程中就不对了。
引用 4 楼 sp1234 的回复:
首先在业务通讯协议设计方面,我们能够想到的最蠢的方法,可能就是轮询了。假设只有这一种办法得到新数据,那么是悲哀的。 然后就算是如此读取数据,你读取数据跟显示也是两个异步过程,设计到一个同步过程中就不对了。
引用 4 楼 sp1234 的回复:
首先在业务通讯协议设计方面,我们能够想到的最蠢的方法,可能就是轮询了。假设只有这一种办法得到新数据,那么是悲哀的。 然后就算是如此读取数据,你读取数据跟显示也是两个异步过程,设计到一个同步过程中就不对了。
你就是个 猴子请来的豆逼!
winnowc 2014-10-24
  • 打赏
  • 举报
回复
可以看下我写的这个原型有没有帮助:https://code.csdn.net/snippets/495283 这就是在一个线程模拟每50ms生成一条数据,然后UI上每200ms更新grid的代码。这个没考虑更多,只是看看和想要的"实时刷新"有什么距离。
  • 打赏
  • 举报
回复
关键点是50ms,50ms真心没必要,ui的刷新对系统的消耗挺大,1s 3s 甚至5s 其实对用户体验并没有多大区别。 至于数据,读取之后还是最好存储起来。
SomethingJack 2014-10-24
  • 打赏
  • 举报
回复
雷达是50MS收一次数据,按照你们所说,如果我抛开这个50MS 那么是直接在内存处理好 还是先入库数据库? 需求跟技术上实现基本都是我要考虑的 因为现在有一款老外写的软件,我看他的数据是实时刷新 也没有安装什么数据库之类的
绿领巾童鞋 2014-10-24
  • 打赏
  • 举报
回复
引用 2 楼 bdmh 的回复:
用线程,把接收到的数据放到list中,不作处理,后台开一个线程对list中的数据循环做处理,处理完了通知UI更新界面
+1,接收跟窗体处理操作分开,还有理清刷新窗体所需的数据已经接收数据缓冲容器的关系。
QQ234788028 2014-10-24
  • 打赏
  • 举报
回复
线程线程线程
x1983c 2014-10-24
  • 打赏
  • 举报
回复
50ms的刷新频率,显示出来的数据人眼根本就看不到,建立lz把这个业务分析清楚,最好能辨别出用人有用的数据转换成有用的信息,再显示出来。
SomethingJack 2014-10-24
  • 打赏
  • 举报
回复
引用 31 楼 github_22161131 的回复:
我不了解具体需求,也不知道数据结构和界面具体是什么样子的,也帮不了更多了。 那个原型代码估计也就是用了个ConcurrentQueue有些陌生。因为需要一个线程安全的结构来在两个线程之间传递数据,这些Concurrent开头的结构能够保证并发读写的线程安全,这个结构的功能也可以被一个数据库替换。可以把它想象成一个数据池,一方不断往里面填数据,另一方不断从里面取数据。 然后就是UI控件不能直接绑定到这个结构上,需要隔离开才能保证UI不会对数据的生产方发生影响。所以把数据池里面的数据放到了一个专门做绑定用的BindingList里,它可以通过自己的变化直接触发UI更新,方便一点。 这个后面还需要处理内存增长的问题,和界面能一次加载多少数据的问题。
行 我结贴了 感谢 遇到问题再说 已经关注你 谢谢!
winnowc 2014-10-24
  • 打赏
  • 举报
回复
我不了解具体需求,也不知道数据结构和界面具体是什么样子的,也帮不了更多了。 那个原型代码估计也就是用了个ConcurrentQueue有些陌生。因为需要一个线程安全的结构来在两个线程之间传递数据,这些Concurrent开头的结构能够保证并发读写的线程安全,这个结构的功能也可以被一个数据库替换。可以把它想象成一个数据池,一方不断往里面填数据,另一方不断从里面取数据。 然后就是UI控件不能直接绑定到这个结构上,需要隔离开才能保证UI不会对数据的生产方发生影响。所以把数据池里面的数据放到了一个专门做绑定用的BindingList里,它可以通过自己的变化直接触发UI更新,方便一点。 这个后面还需要处理内存增长的问题,和界面能一次加载多少数据的问题。
SomethingJack 2014-10-24
  • 打赏
  • 举报
回复
引用 28 楼 github_22161131 的回复:
[quote=引用 27 楼 SomethingJack 的回复:] 明白了 感谢 ,还有最后一个问题,就是我现在的雷达最大的目标扫描数量是9个. 也就是说,ID只能是0-9.然后每一个ID的后面的字段是实时变化的,比如开始1,然后按照你的程序200MS这个值可以直观的看到改变了。9个目标都是这样 ID不变。
没看出来问题是什么[/quote] 我的意思是 实际上 雷达扫描的数据一共有9个目标 也就是有9个ID 但是每个目标的其他字段数据是在不断改变的, 能麻烦你改造一下你得例子么。9个ID不变 其余的字段数据200MS改变刷新一次。 我还在消化你的代码
ZhongGuanYao 2014-10-24
  • 打赏
  • 举报
回复
50ms刷新一次界面,就算不卡,但频率过高肉眼也看不清楚啊,先将数据保存到内存中的List,1秒后再刷新界面并将数据写入到硬盘数据库或文件中,清空List再保存下一批,建议用后台线程处理数据吧
winnowc 2014-10-24
  • 打赏
  • 举报
回复
引用 27 楼 SomethingJack 的回复:
明白了 感谢 ,还有最后一个问题,就是我现在的雷达最大的目标扫描数量是9个. 也就是说,ID只能是0-9.然后每一个ID的后面的字段是实时变化的,比如开始1,然后按照你的程序200MS这个值可以直观的看到改变了。9个目标都是这样 ID不变。
没看出来问题是什么
SomethingJack 2014-10-24
  • 打赏
  • 举报
回复
引用 25 楼 github_22161131 的回复:
[quote=引用 22 楼 SomethingJack 的回复:] [quote=引用 20 楼 github_22161131 的回复:] 可以看下我写的这个原型有没有帮助:https://code.csdn.net/snippets/495283 这就是在一个线程模拟每50ms生成一条数据,然后UI上每200ms更新grid的代码。这个没考虑更多,只是看看和想要的"实时刷新"有什么距离。
_timer = new System.Windows.Forms.Timer(components) { Interval = 200 }; 谢谢你的回答,这个地方的components参数报错了 你测试过代码了么?[/quote] 我当然测试过,WinForm的designer有时不生成这个components,去掉就是。[/quote] 明白了 感谢 ,还有最后一个问题,就是我现在的雷达最大的目标扫描数量是9个. 也就是说,ID只能是0-9.然后每一个ID的后面的字段是实时变化的,比如开始1,然后按照你的程序200MS这个值可以直观的看到改变了。9个目标都是这样 ID不变。
於黾 2014-10-24
  • 打赏
  • 举报
回复
引用 23 楼 SomethingJack 的回复:
[quote=引用 19 楼 LessOrMore 的回复:] 关键点是50ms,50ms真心没必要,ui的刷新对系统的消耗挺大,1s 3s 甚至5s 其实对用户体验并没有多大区别。 至于数据,读取之后还是最好存储起来。
谢谢回答 照大家的想法看来 我必须使用什么方式存储再显示了。[/quote] 如果你的数据只是用于实时显示,不需要查看历史,那么没必要存储,过期数据可以直接丢弃了 总之,采集数据和显示数据的过程要分开,不要都混到一个逻辑里去
winnowc 2014-10-24
  • 打赏
  • 举报
回复
引用 22 楼 SomethingJack 的回复:
[quote=引用 20 楼 github_22161131 的回复:] 可以看下我写的这个原型有没有帮助:https://code.csdn.net/snippets/495283 这就是在一个线程模拟每50ms生成一条数据,然后UI上每200ms更新grid的代码。这个没考虑更多,只是看看和想要的"实时刷新"有什么距离。
_timer = new System.Windows.Forms.Timer(components) { Interval = 200 }; 谢谢你的回答,这个地方的components参数报错了 你测试过代码了么?[/quote] 我当然测试过,WinForm的designer有时不生成这个components,去掉就是。
卧_槽 2014-10-24
  • 打赏
  • 举报
回复
50ms异步刷新gridview速度上应该是够的。50ms刷新一次,也就是每秒20帧。 创建合适的数据对象,绑定到gridview的datasource上。接收新数据后,更新数据源对象。更新后局部刷新变化了的数据。 如果还觉得卡,可以调试和创建测试查看这个过程耗时的代码在哪里,进行优化,如果是ui反应不过来,那只好降低帧率,比如接收次数单次的数据不处理,只处理双次的,这样可以做到每秒10帧,gdi+应该可以处理过来了。 最后:用gridview显示变化的数据不觉得很愚昧么?谁会盯着一个表格看上面的数字跳来跳去?
SomethingJack 2014-10-24
  • 打赏
  • 举报
回复
引用 19 楼 LessOrMore 的回复:
关键点是50ms,50ms真心没必要,ui的刷新对系统的消耗挺大,1s 3s 甚至5s 其实对用户体验并没有多大区别。 至于数据,读取之后还是最好存储起来。
谢谢回答 照大家的想法看来 我必须使用什么方式存储再显示了。
SomethingJack 2014-10-24
  • 打赏
  • 举报
回复
引用 20 楼 github_22161131 的回复:
可以看下我写的这个原型有没有帮助:https://code.csdn.net/snippets/495283 这就是在一个线程模拟每50ms生成一条数据,然后UI上每200ms更新grid的代码。这个没考虑更多,只是看看和想要的"实时刷新"有什么距离。
_timer = new System.Windows.Forms.Timer(components) { Interval = 200 }; 谢谢你的回答,这个地方的components参数报错了 你测试过代码了么?
cainiao77 2014-10-24
  • 打赏
  • 举报
回复
用Timer试试。
加载更多回复(14)

110,499

社区成员

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

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

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