C# Winforms 中的 UI 渲染缓慢

     2023-04-15     228

关键词:

【中文标题】C# Winforms 中的 UI 渲染缓慢【英文标题】:Slow UI rendering in C# Winforms 【发布时间】:2017-01-30 19:45:09 【问题描述】:

我正在制作一个相对基本的WinForms 用户控件,其中包含许多按钮,每个按钮代表数据库中的一个表。

在调用InitializeComponent方法后,每个表中的数据被加载到对应的DataGridView中。

当单击上述按钮之一时,其对应的DataGridView 以及那些通过 FK 链接到主按钮的代表表变得可见,然后 BackgroundWorker 逐渐将它们增加到所需的大小并将控件转移到适当的位置在短时间内。

public uc1()

    InitializeComponent();

    PopulateTables();

    tableResizer.WorkerReportsProgress = true;
    tableResizer.WorkerSupportsCancellation = true;
    tableResizer.DoWork += tableResizer_DoWork;
    tableResizer.ProgressChanged += tableResizer_ProgressChanged;
    tableResizer.RunWorkerCompleted += tableResizer_RunWorkerCompleted;

    dgv5.SelectionChanged += show5Relations;


private void btn5_Click(object sender, EventArgs e)

    mainTable = 5;
    btn5.Visible = false;
    btn4.Visible = false;
    btn3.Visible = false;
    btn2.Visible = false;
    dgv5.Visible = true;
    dgv4.Visible = true;
    dgv3.Visible = true;
    dgv2.Visible = true;
    lbl6.Visible = false;
    lbl7.Visible = false;
    lbl1.Visible = false;
    tableResizer.RunWorkerAsync();


private void tableResizer_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)

    int expansion = 0;
    while (expansion < 30)
    
        tableResizer.ReportProgress(mainTable);
        expansion++;
        System.Threading.Thread.Sleep(16);
    


private void tableResizer_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)

    if (e.ProgressPercentage == 5)
    
        dgv5.Size = new Size(dgv5.Size.Width + (((this.Width / 26) * 10) / 30), dgv5.Size.Height + (((this.Height / 24) * 10) / 30));
        dgv5.Location = new Point(dgv5.Location.X - (((this.Width / 26) * 10) / 60), dgv5.Location.Y - (((this.Height / 24) * 10) / 60));

        dgv4.Size = new Size(dgv4.Size.Width + (((this.Width / 26) * 10) / 30), dgv4.Size.Height + (((this.Height / 24) * 10) / 50));
        dgv4.Location = new Point(dgv4.Location.X - (((this.Width / 26) * 10) / 40), dgv4.Location.Y - (((this.Height / 24) * 10) / 120));

        dgv3.Size = new Size(dgv3.Size.Width + (((this.Width / 26) * 10) / 30), dgv3.Size.Height + (((this.Height / 24) * 10) / 50));
        dgv3.Location = new Point(dgv3.Location.X - (((this.Width / 26) * 10) / 40), dgv3.Location.Y - (((this.Height / 24) * 10) / 120));

        dgv2.Size = new Size(dgv2.Size.Width + (((this.Width / 26) * 10) / 30), dgv2.Size.Height + (((this.Height / 24) * 10) / 50));
        dgv2.Location = new Point(dgv2.Location.X - (((this.Width / 26) * 10) / 40), dgv2.Location.Y - (((this.Height / 24) * 10) / 120));

        btn1.Location = new Point(btn1.Location.X - (((this.Width / 26) * 10) / 130), btn1.Location.Y);
    


private void tableResizer_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)

    if (mainTable == 5)
    
        btn7.Visible = true;
        btn6.Visible = true;
        btn1.Visible = true;
        lbl5.Visible = true;
        lbl5.Location = new Point(dgv5.Location.X, dgv5.Location.Y - lbl5.Size.Height);
        lbl4.Visible = true;
        lbl4.Location = new Point(dgv4.Location.X, dgv4.Location.Y - lbl4.Size.Height);
        lbl3.Visible = true;
        lbl3.Location = new Point(dgv3.Location.X, dgv3.Location.Y - lbl3.Size.Height);
        lbl2.Visible = true;
        lbl2.Location = new Point(dgv2.Location.X, dgv2.Location.Y - lbl1.Size.Height);
    

问题在于,当tableResizer 工作时,UI 的渲染速度不够快,因此,DataGridViews 之一在工作完成之前无法完全可见。

DoWork 方法中增加睡眠的长度仅在 60 毫秒时解决了这个问题,此时渲染太不稳定而无法接受。任何超过 30 毫秒的都不会做。

我对多线程和 C# 比较陌生,所以我很确定有更有效的方法来解决这个问题。

我应该怎么做才能保证流畅的渲染?

【问题讨论】:

如果您使用BackgroundWorker 只是动画,那么请改用System.Timers.TimerSystem.Threading.Timer 【参考方案1】:

我找到了解决问题的方法。虽然我之前曾尝试将用户控件的DoubleBuffered 设置为true,但它没有帮助。问题是 DataGridViews 默认关闭它,因为它是受保护的属性,所以不能设置为 true。

在进一步调查这个问题(我应该早点做,我很抱歉)后,我发现了这个已回答的问题: Horrible redraw performance of the DataGridView on one of my two screens

解决方案非常简单。创建一个继承自默认DataGridView 的类并将其DoubleBuffered 属性分配为true。

class CustomDataGridView: DataGridView

    public CustomDataGridView()
    
        DoubleBuffered = true;
     

【讨论】:

WinForms 栅格地图渲染控件

】WinForms栅格地图渲染控件【英文标题】:WinFormsrastermapsrenderingcontrol【发布时间】:2011-08-3021:14:07【问题描述】:将地图视为一组栅格图块(每个缩放级别一组)。基本上,地图在GoogleMaps、BingMaps等中的存储方式是相同的。我需... 查看详情

如何将 UI 与 C# 中的渲染分开?

】如何将UI与C#中的渲染分开?【英文标题】:HowdoIseparateUIfromrenderinginC#?【发布时间】:2014-03-1516:59:35【问题描述】:我正在尝试用C#编写游戏循环,但我无法从另一个线程访问WPF对象...基本上这就是我想要的循环:循环:读取... 查看详情

c# 中的解决方案架构,其中 winforms 和 asp.mvc 共享业务逻辑和数据访问 [关闭]

】c#中的解决方案架构,其中winforms和asp.mvc共享业务逻辑和数据访问[关闭]【英文标题】:solutionarchitectureinc#wherewinformsandasp.mvcsharebusinesslogicandDataaccess[closed]【发布时间】:2016-07-2422:40:07【问题描述】:我有一个c#winforms解决方案... 查看详情

C# WinForms 中的切换按钮

】C#WinForms中的切换按钮【英文标题】:ToggleButtoninC#WinForms【发布时间】:2010-09-2121:06:50【问题描述】:是否可以在C#WinForms中创建切换按钮?我知道您可以使用CheckBox控件并将其Appearance属性设置为“Button”,但它看起来不正确。... 查看详情

Winforms 中的 C# 单词数组帮助

】Winforms中的C#单词数组帮助【英文标题】:C#wordarrayhelpinWinforms【发布时间】:2021-12-2215:59:57【问题描述】:所以在我的课堂上,我们正在使用Winforms进行猪拉丁语翻译。如果我将公式从我的Convert函数复制到click事件,它对于1个... 查看详情

WinForms 中的 C# 虚拟列表视图

】WinForms中的C#虚拟列表视图【英文标题】:C#VirtualListViewinWinForms【发布时间】:2020-08-3017:30:11【问题描述】:我不熟悉虚拟列表项及其工作原理。您能解释一下用途以及何时适合使用。可以与word文档文本文件,excel文档一起使... 查看详情

Winforms (C#) 中的 OleDb 参数查询:没有错误但没有更新行

】Winforms(C#)中的OleDb参数查询:没有错误但没有更新行【英文标题】:OleDbparameterqueryinWinforms(C#):noerrorsbutnorowsupdated【发布时间】:2015-06-0914:50:22【问题描述】:我正在尝试更新MSAccess中的表,但更新操作不起作用并且我没有收到... 查看详情

c# GDI和winforms中的径向渐变画笔效果

】c#GDI和winforms中的径向渐变画笔效果【英文标题】:c#radialgradientbrusheffectinGDIandwinforms【发布时间】:2011-03-3123:52:46【问题描述】:我创建了一个c#windows应用程序并编写了75%的代码。该程序允许用户创建流程图,并根据其状态对... 查看详情

C# Winforms 按钮到 Windows 中的特定屏幕

】C#Winforms按钮到Windows中的特定屏幕【英文标题】:C#WinformsbuttontospecificscreeninWindows【发布时间】:2015-02-2802:23:18【问题描述】:我正在编写一个应用程序来更改网络适配器IP地址设置。只有基本的IP设置是我将从应用程序中更改... 查看详情

C# WinForms - DataGridView/SQL Compact - 主键列中的负整数

】C#WinForms-DataGridView/SQLCompact-主键列中的负整数【英文标题】:C#WinForms-DataGridView/SQLCompact-Negativeintegerinprimarykeycolumn【发布时间】:2010-09-0712:00:09【问题描述】:我刚刚开始使用WinForms,并且通过一个可爱的教程,我发现了将数据... 查看详情

检测是不是在 WPF 和 Winforms 中的 UI 线程上

】检测是不是在WPF和Winforms中的UI线程上【英文标题】:DetectingwhetheronUIthreadinWPFandWinforms检测是否在WPF和Winforms中的UI线程上【发布时间】:2011-07-0520:12:43【问题描述】:我在下面编写了一个断言方法Ensure.CurrentlyOnUiThread(),用于检... 查看详情

如何避免Winforms c#中的Reflected_xss_all_clients漏洞

】如何避免Winformsc#中的Reflected_xss_all_clients漏洞【英文标题】:HowtoavoidReflected_xss_all_clientsvulnerabilitiesinWinformsc#【发布时间】:2021-05-0109:01:27【问题描述】:目前,我正在为一个Winforms项目工作。当我通过CheckMarx扫描我的Winforms应... 查看详情

哪个日志实用程序适用于 C#(ASP.NET、WinForms)中的 .NET 应用程序? [关闭]

】哪个日志实用程序适用于C#(ASP.NET、WinForms)中的.NET应用程序?[关闭]【英文标题】:Whichlogutilityisgoodfor.NETapplicationinC#(ASP.NET,WinForms)?[closed]【发布时间】:2011-01-0715:08:12【问题描述】:我正在尝试评估一些可用于.NET框架的最... 查看详情

如何使窗口可拖动(C# Winforms)?

】如何使窗口可拖动(C#Winforms)?【英文标题】:HowtomakeawindowDraggable(C#Winforms)?【发布时间】:2011-04-2901:02:34【问题描述】:我有形式。我已启用表单的透明度,并删除了它的标题栏和边框。在里面,我创建了一个自定义UI,它... 查看详情

在 C# winforms 中的同一表单上从一个 webBrowser 导航到另一个 webBrowser

】在C#winforms中的同一表单上从一个webBrowser导航到另一个webBrowser【英文标题】:navigatefromonewebBrowsertoanotherwebBrowseronthesameforminC#winforms【发布时间】:2014-02-0311:20:22【问题描述】:我有一个名为webBrowser3的webBrowser,它显示指向其HTM... 查看详情

C# WinForms TextBox 等的垂直对齐

】C#WinFormsTextBox等的垂直对齐【英文标题】:C#WinFormsVerticalAlignmentforTextBox,etc【发布时间】:2011-02-0820:04:48【问题描述】:我正在开发一个项目,更新他们的WinForms应用程序UI,使其与尺寸更加一致。默认情况下,TextBox和ComboBox控... 查看详情

BackgroundWorker,我怎样才能显示真正的进步? C# Winforms

】BackgroundWorker,我怎样才能显示真正的进步?C#Winforms【英文标题】:BackgroundWorker,howCouldishowrealprogress?C#Winforms【发布时间】:2021-11-1615:50:28【问题描述】:我创建了使用AES加密/解密文件的应用程序,但是当我需要处理大文件时... 查看详情

在 C# winforms 中读取 csv 文件时出现数据错误

】在C#winforms中读取csv文件时出现数据错误【英文标题】:dataerrorwhenreadingcsvfileinC#winforms【发布时间】:2012-01-3018:37:06【问题描述】:我有一个C#winforms正在从csv文件中读取一列。它正确读取了4列中的3列。csv文件中的第4列是S4,... 查看详情