C# WinForm DataGridView 非常频繁地更新或重新绘制慢问题及解决
非常频繁地更新 DataGridView问题描述:
在 C# 中无法在合理的时间内刷新我的 DataGridView ,我每秒通过网络发送 20 个数据包,获取数据。我想解析这些数据并将其放入 DataGridView 中。我还想调整 DataGridView 的更新间隔,从 0.1 秒到 1 分钟。
因此,我创建了一个额外的线程,用于读取包并将其解析为数组。我还创建了一个计时器,用于更改间隔。每次计时器计时,我都会将 DataSource 重新分配给 DataGridView。
有趣的是,当我这样做时,即使我将计时器设置为 0.1 秒,它也只会每秒触发一次。如果我不刷新 DataGridView,它每秒就会触发 10 次,正如预期的那样。
所以我认为我更新 DataGridView 的方法太耗时了。但是我该怎么做才能让它更高效,以便每秒更新 10 次而不会出现任何问题呢?
这是使用的代码:
public MyForm()
{
InitializeComponent();
timer = new System.Windows.Forms.Timer();
timer.Interval = (1 * 1000); // 1 secs
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
readNetworkValues = true;
networkReader = new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 49003);
UdpClient newsock = new UdpClient(ipep);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
while (readNetworkValues)
{
data = newsock.Receive(ref sender);
dataSet = parseData(data); //Decrypts the data
}
newsock.Close();
});
networkReader.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
if (dataSet != null)
{
lock (dataSet)
{
int currentRow = dataGrid.FirstDisplayedScrollingRowIndex;
dataGrid.DataSource = dataSet;
dataGrid.FirstDisplayedScrollingRowIndex = currentRow;
}
}
}
解决方法:
您想要更新的单元数量以及您想要的更新率足够高,从而导致闪烁和延迟。
为了避免这种情况,您可以DoubleBuffering打开DataGridView。
此属性默认不公开。因此,您可以选择创建子类或通过反射访问它,它主要针对滚动闪烁的情况,但也有助于避免更新延迟。类可能看起来像这样:
public class DBDataGridView : DataGridView
{
public new bool DoubleBuffered
{
get { return base.DoubleBuffered; }
set { base.DoubleBuffered = value; }
}
public DBDataGridView()
{
DoubleBuffered = true;
}
}
您可以将此类添加到项目中,或者仅添加到表单类中(在最后一个花括号之前)。编译后它将显示在工具箱中。
另一个选项是使用反射;这是一个适用于任何类型控件的通用函数:
using System.Reflection;
static void SetDoubleBuffer(Control ctl, bool DoubleBuffered)
{
typeof(Control).InvokeMember("DoubleBuffered",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
null, ctl, new object[] { DoubleBuffered });
}
两种方式都可以DoubleBuffering随意打开和关闭;前者通过现在公开的属性,后者通过bool方法的参数。
DataGridView 重新绘制慢问题描述:
我知道有几个关于速度慢的 DataGridViews 的问题,确实尝试了那里提到的所有内容,大多数都是关于更复杂的数据绑定。
之前做过的事情:
测试了 DataTable 作为数据源
未绑定的 Datagridview,循环填充
使用 autoColumnResizing 等测试了许多设置,但所有测试都太慢了。
此示例仅是主窗体中的一个 datgridview,来自设计器工具箱的普通库存,已编辑。
即使只有 100 行,滚动和重新绘制时也会感觉非常滞后,并且会占用一个核心的最大值。
我在 datagridview 中滚动时进行了 VS 分析器会话:
想深入挖掘并了解究竟是什么让这个控制如此缓慢,以及可以做些什么来加速它,或者可以使用什么替代方法来获得一个可以通过单击列标题进行排序的快速表。
测试代码:
public partial class Form1 : Form
{
List<Record> myData;
public Form1()
{
InitializeComponent();
myData = getListofRecord();
dataGridView1.DataSource = myData;
}
private static List<Record> getListofRecord()
{
var myTable = new List<Record>();
for (int i = 0; i < 500; i++)
{
myTable.Add(new Record() { a = 121+i, b = 123.2434F, c = 2342, d = 312+i*2, e = 123343, f = 12323 });
}
return myTable;
}
}
public class Record
{
public Single a { get; set; }
public Single b { get; set; }
public Single c { get; set; }
public Single d { get; set; }
public Single e { get; set; }
public Single f { get; set; }
}
编辑1:
两天后,我在同一台机器上重新运行测试应用时得到了不同的结果。它的速度和我预期的一样快,分析结果或许能解释热路径堆栈中缺失的原因。
编辑2:
无论第一个差异背后的真正原因是什么,通过反射启用双缓冲的效果最为明显,大约提升了 20 倍。 我在其他 DGV 问题中也看到过类似的建议,但我原本只期望获得轻微的视觉效果提升,而不是全新的体验。
分析热路径现在显示完全不同的调用堆栈。
编辑3:
为了保存我在这个问题中的分析工作,避免被当作重复数据删除,想获取一些以毫秒为单位的目标数据,用于重新绘制DGV。需要把秒表放在哪里才能获取这些数据?
解决方法:
其实与上面闪烁方法一致,方法就这么简单:
C#.NET:
using System.Reflection;
static void SetDoubleBuffer(Control dgv, bool DoubleBuffered)
{
typeof(Control).InvokeMember("DoubleBuffered",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
null, dgv, new object[] { DoubleBuffered });
}
VB.NET:
Public Sub DoubleBuffered(ByVal dgv As DataGridView, ByVal setting As Boolean)
Dim dgvType As Type = dgv.[GetType]()
Dim pi As PropertyInfo = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance Or BindingFlags.NonPublic)
pi.SetValue(dgv, setting, Nothing)
End Sub
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。
相关文章:

C# WinForm DataGridView 非常频繁地更新或重新绘制慢问题及解决
非常频繁地更新 DataGridView问题描述: 在 C# 中无法在合理的时间内刷新我的 DataGridView ,我每秒通过网络发送 20 个数据包,获取数据。我想解析这些数据并将其放入 DataGridView 中。我还想调整 DataGridView 的更新间隔,从 0.1…...

【数据结构】红黑树(C++)
目录 一、红黑树的概念 二、红黑树的性质 三、红黑树结点定义 四、红黑树的操作 1. 插入操作 1.1 插入过程 1.2 调整过程 1.2.1 叔叔节点存在且为红色 1.2.2 叔叔节点存在且为黑色 1.2.3 叔叔节点不存在 2. 查找操作 2.1 查找逻辑 2.2 算法流程图 2.3 使用示例 …...
验证码与登录过程逻辑学习总结
目录 前言 一、验证码与登录 二、使用步骤 1.先apipost测试一波 2.先搞验证码 3.跨域问题 4.后端走起 总结 前言 近期要做一个比较完整的demo,需要自己做一个前端登录页面,不过api接口都是现成的,一开始以为过程会很easy,…...

Android Framework学习五:APP启动过程原理及速度优化
文章目录 APP启动优化概述APP启动流程点击图片启动APP的过程启动触发Zygote 与应用进程创建Zygote进程的创建应用进程初始化 ApplicationActivity 启动与显示 优化启动时黑白屏现象可优化的阶段Application阶段相关优化 Activity阶段数据加载阶段 Framework学习系列文章 APP启动…...

Meta的AIGC视频生成模型——Emu Video
大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本文详细介绍Meta的视频生成模型Emu Video,作为Meta发布的第二款视频生成模型,在视频生成领域发挥关键作用。 🌺优质专栏回顾&am…...

Axure难点解决分享:统计分析页面引入Echarts示例动态效果
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:统计分析页面引入Echarts示例动态效果 主要内容:echart示例引入、大小调整、数据导入 应用场景:统计分析页面…...

Docker 常见问题及其解决方案
一、安装与启动问题 1.1 安装失败 在不同操作系统上安装 Docker 时,可能会出现安装失败的情况。例如,在 Ubuntu 系统中,执行安装命令后提示依赖缺失。这通常是因为软件源配置不正确或系统缺少必要的依赖包。 解决方案: 确保系统…...
后端开发面试高频50个问题,简单解答
以下是后端开发面试中常见的50个高频问题及其详细解答,涵盖了语言基础、数据库、网络、操作系统、设计模式等多个方面: 编程语言基础 Java 中的 final 关键字有什么作用? final 可以修饰类、方法和变量。修饰类时,类不能被继承&am…...

IC解析之TPS92682-Q1(汽车LED灯控制IC)
目录 1 IC特性介绍2 主要参数3 接口定义4 工作原理分析TPS92682-Q1架构工作模式典型应用通讯协议 控制帧应答帧协议5 总结 1 IC特性介绍 TPS92682 - Q1 是德州仪器(TI)推出的一款双通道恒压横流控制器,同时还具有各种电器故障保护,…...

6.01 Python中打开usb相机并进行显示
本案例介绍如何打开USB相机并每隔100ms进行刷新的代码,效果如下: 一、主要思路: 1. 打开视频流、读取帧 self.cam_cap = cv2.VideoCapture(0) #打开 视频流 cam_ret, cam_frame = self.cam_cap.read() //读取帧。 2.使用定时器,每隔100ms读取帧 3.显示到Qt的QLabel…...

2023华为od统一考试B卷【二叉树中序遍历】
前言 博主刷的华为机考题,代码仅供参考,因为没有后台数据,可能有没考虑到的情况 如果感觉对你有帮助,请点点关注点点赞吧,谢谢你! 题目描述 思路 0.用Character数组存储树,index下标的左右…...
计算机网络:计算机之间的数据传输为什么要以时钟频率同步为基础?
以太网信息同步需要保障时钟同步的主要原因包括以下几点: 1. 确保数据的准确采样与解析 比特级同步:以太网数据传输以连续的比特流形式进行,接收端需在精确的时间点对信号采样。若发送端与接收端时钟不同步,采样时机偏移会导致误…...

在Spark搭建YARN
(一)什么是SparkONYarn模式 Spark on YARN(Yet Another Resource Negotiator)是 Spark 框架在 Hadoop 集群中运行的一种部署模式,它借助 Hadoop YARN 来管理资源和调度任务。 架构组成 ResourceManager:作…...

LeetCode_sql刷题(3482.分析组织层级)
题目描述:3482. 分析组织层级 - 力扣(LeetCode) 表:Employees ------------------------- | Column Name | Type | ------------------------- | employee_id | int | | employee_name | varchar | | manager_id …...
Python 之 selenium 打开浏览器指定端口进行接续操作
一般使用 selenium 进行数据爬取时,常用处理流程是让 selenium 从打开浏览器开始,完成全流程的所有操作。但是有时候,我们希望用户先自己打开浏览器进入指定网页,完成登录认证等一系列操作之后(比如用户、密码、短信验…...
MySQL Explain 中 Type 与 Extra 字段详解
引言 在数据库性能调优过程中,理解执行计划(EXPLAIN)的输出信息至关重要。MySQL 的 EXPLAIN 命令能够帮助开发者分析查询的执行路径和效率,其中 Type 和 Extra 字段提供了关键的执行细节。Type 字段表示访问类型,反映…...

不用服务器转码,Web端如何播放RTSP视频流?
在物联网、智慧城市、工业互联网等新兴技术浪潮下,实时视频流(如RTSP协议)作为安防监控、生产巡检、远程协作等场景的核心数据载体,其价值愈发凸显。然而,一个长期困扰行业的痛点始终存在——如何在Web浏览器中直接播…...

如何开发一款 Chrome 浏览器插件
Chrome是由谷歌开发的网页浏览器,基于开源软件(包括WebKit和Mozilla)开发,任何人都可以根据自己需要使用、修改或增强它的功能。Chrome凭借着其优秀的性能、出色的兼容性以及丰富的扩展程序,赢得了广大用户的信任。市场…...

GitHub打开缓慢甚至失败的解决办法
在C:\Windows\System32\drivers\etc的hosts中增加如下内容: 20.205.243.166 github.com 199.59.149.236 github.global.ssl.fastly.net185.199.109.153 http://assets-cdn.github.com 185.199.108.153 http://assets-cdn.github.com 185.199.110.153 http://asset…...

18前端项目----Vue项目收尾优化|重要知识
收尾/知识点汇总 项目收尾二级路由未登录全局路由守卫路由独享守卫图片懒加载路由懒加载打包上线 重要知识点汇总组件通信方式1. props2. 自定义事件3. 全局事件总线4. 订阅与发布pubsub5. Vuex6. 插槽 sync修饰符attrs和listeners属性children和parent属性mixin混入作用域插槽…...

仿RabbitMQ 模拟实现消息队列
文章目录 项目项目介绍开发环境技术选型 开始项目前第三方框架内容介绍muduo搭建服务端,客户端服务端:客户端:makefile muduo库protobuf通信服务端:客户端 sqlitegtest线程池future 认识,async使用promis使用package_t…...

基于Qt的app开发第八天
写在前面 笔者是一个大一下计科生,本学期的课程设计自命题完成一个督促学生自律的打卡软件,目前已经完成了待办和打卡部分功能,本篇要完成规划板块不需要存储就能实现的功能 需求分析 这一板块内容相比前两个板块还有一些特殊,因…...
Springboot之类路径扫描
SpringBoot框架中默认提供的扫描类为:ClassPathBeanDefinitionScanner。 webFlux框架中借助RepositoryComponentProvider扫描符合条件的Repository。 public class ClassPathScanningCandidateComponentProvider{private final List<TypeFilter> includeFilt…...
PNG图片转icon图标Python脚本(简易版) - 随笔
摘要 在网站开发或应用程序设计中,常需将高品质PNG图像转换为ICO格式图标。本文提供一份高效Python解决方案,利用Pillow库实现透明背景完美保留的格式转换。 源码示例 from PIL import Imagedef convert_png_to_ico(png_path, ico_path, size):"…...

数据分析-图2-图像对象设置参数与子图
from matplotlib import pyplot as mp mp.figure(A figure,facecolorgray) mp.plot([0,1],[1,2]) mp.figure(B figure,facecolorlightgray) mp.plot([1,2],[2,1]) #如果figure中标题已创建,则不会新建窗口, #而是将旧窗口设置为当前窗口 mp.figure(A fig…...

查询公网IP地址的方法:查看自己是不是公网ip,附内网穿透外网域名访问方案
本地搭建服务并提供互联网连接时,较为传统的方法是使用公网IP地址。因此,如何查询本地自己是不是公网IP,是必须要掌握的一种技巧。当面对确实无公网IP时,则可以通过内网穿透方案,如nat123网络映射工具,将本…...
MVCC:数据库并发控制的利器
在并发环境下,数据库需要处理多个事务同时访问和修改数据的情况。为了保证数据的一致性和隔离性,数据库需要采用一些并发控制机制。MVCC (Multi-Version Concurrency Control,多版本并发控制) 就是一种常用的并发控制技术,它通过维…...

Redis学习打卡-Day1-SpringDataRedis、有状态无状态
Redis的Java客户端 Jedis 以 Redis 命令作为方法名称,学习成本低,简单实用。Jedis 是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此推荐使用 Jedis 连接池代替Jedis的直连方式。 lettuce Lettuce是基于Netty实现的&am…...
【行为型之访问者模式】游戏开发实战——Unity灵活数据操作与跨系统交互的架构秘诀
文章目录 🧳 访问者模式(Visitor Pattern)深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码(游戏物品系统)1. 定义元素与访问者接口2. 实现具体元素类3. 实现具体访问者4. 对象结构管理5. 客户端使用 …...
Shell脚本实践(修改文件,修改配置文件,执行jar包)
1、前言 需要编写一个shell脚本支持 1、修改.so文件名 2、修改配置文件 3、执行jar包 2、代码解析 2.1、修改.so文件名 so_file_dir="/opt/casb/xxx/lib" # 处理.so文件 cd "$so_file_dir" || { echo "错误: 无法进入目录 $so_file_dir"; exit …...