C#使用ListView更新数据出现闪烁解决办法

C#使用ListView更新数据出现闪烁解决办法

在使用vs自动控件ListView控件时候,更新里面的部分代码时候出现闪烁的情况

如图:

 

解决以后:

 

解决办法使用双缓冲:添加新类继承ListView 对其重写

复制代码
 1 public class DoubleBufferListView : ListView2     {3         public DoubleBufferListView()4         {5             SetStyle(ControlStyles.DoubleBuffer |6               ControlStyles.OptimizedDoubleBuffer |7               ControlStyles.AllPaintingInWmPaint, true);8             UpdateStyles();9         }
10     }
复制代码

新建一个DemoTest测试

 

1.添加一个DoubleBufferListView的实例

复制代码
       DoubleBufferListView doubleBufferListView1= new DoubleBufferListView();// // doubleBufferListView1// this.doubleBufferListView1.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));this.doubleBufferListView1.FullRowSelect = true;this.doubleBufferListView1.HideSelection = false;this.doubleBufferListView1.Location = new System.Drawing.Point(50, 37);this.doubleBufferListView1.Name = "doubleBufferListView1";this.doubleBufferListView1.Size = new System.Drawing.Size(400, 191);this.doubleBufferListView1.TabIndex = 2;this.doubleBufferListView1.UseCompatibleStateImageBehavior = false;this.doubleBufferListView1.View = System.Windows.Forms.View.Details;
复制代码

2.将其添加到form窗体里面

 this.Controls.Add(this.doubleBufferListView1);

3.给添加列

        doubleBufferListView1.Clear();doubleBufferListView1.Columns.Add("Action", 80, System.Windows.Forms.HorizontalAlignment.Left);doubleBufferListView1.Columns.Add("value", 80, System.Windows.Forms.HorizontalAlignment.Right);doubleBufferListView1.Columns.Add("Action", 80, System.Windows.Forms.HorizontalAlignment.Left);doubleBufferListView1.Columns.Add("value", 80, System.Windows.Forms.HorizontalAlignment.Left);

4.随便添加点内容

复制代码
         string[] listViewData = new string[4];listViewData[0] = "Action";listViewData[1] = "1";listViewData[2] = "Action";listViewData[3] = "1";ListViewItem lvItem = new ListViewItem(listViewData, 0);doubleBufferView1.Items.Add(lvItem);    
复制代码

 

5.点击按钮开始运行

复制代码
 private void button1_Click(object sender, EventArgs e){Thread th = new Thread(PlayGame);if (state == false){state = true;button1.Text = "停止";th.IsBackground = true;th.Name = "新线程";th.Start();}else{state = false;button1.Text = "开始";}}private void PlayGame(){Random r = new Random();while (state){string temp = r.Next(0, 10).ToString();label1.Text = temp;this.doubleBufferListView1.Items[0].SubItems[1].Text = temp;}}
复制代码

6.运行对比图:

左侧是解决闪屏后,右侧是自带的ListView效果

 

原文链接:https://www.cnblogs.com/JiYF/p/6233313.html

 

 

C#中Invoke的用法

在用.NET Framework框架的WinForm构建GUI程序界面时,如果要在控件的事件响应函数中改变控件的状态,例如:某个按钮上的文本原先叫“打开”,单击之后按钮上的文本显示“关闭”,初学者往往会想当然地这么写:

void ButtonOnClick(object sender,EventArgs e)

{

    button.Text="关闭";

}

这样的写法运行程序之后,可能会触发异常,异常信息大致是“不能从不是创建该控件的线程调用它”。注意这里是“可能”,并不一定会触发该种异常。造成这种异常的原因在于,控件是在主线程中创建的(比如this.Controls.Add(...);),进入控件的事件响应函数时,是在控件所在的线程,并不是主线程。在控件的事件响应函数中改变控件的状态,可能与主线程发生线程冲突。如果主线程正在重绘控件外观,此时在别的线程改变控件外观,就会造成画面混乱。不过这样的情况并不总会发生,如果主线程此时在重绘别的控件,就可能逃过一劫,这样的写法可以正常通过,没有触发异常。

正确的写法是在控件响应函数中调用控件的Invoke方法(其实如果大家以前用过C++ Builder的话,也会找到类似Invoke那样的激活到主线程的函数)。Invoke方法会顺着控件树向上搜索,直到找到创建控件的那个线程(通常是主线程),然后进入那个线程改变控件的外观,确保不发生线程冲突。正确写法的示例如下:

void ButtonOnClick(object sender,EventArgs e)

{

    button.Invoke(new EventHandler(delegate

    {

        button.Text="关闭";

    }));

}

Invoke方法需要创建一个委托。你可以事先写好函数和与之对应的委托。不过,若想直观地在Invoke方法调用的时候就看到具体的函数,而不是到别处搜寻的话,上面的示例代码是不错的选择。

这样的写法有一个烦人的地方:对不同的控件写法不同。对于TextBox,要TextBoxObject.Invoke,对于Label,又要LabelObject.Invoke。有没有统一一点的写法呢?

主窗口类本身也有Invoke方法。如果你不想对不同的控件写法不一样,可以全部用this.Invoke:

void ButtonOnClick(object sender,EventArgs e)

{

    this.Invoke(new EventHandler(delegate

    {

        button.Text="关闭";

    }));

}

在C# 3.0及以后的版本中有了Lamda表达式,像上面这种匿名委托有了更简洁的写法。.NET Framework 3.5及以后版本更能用Action封装方法。例如以下写法可以看上去非常简洁:

void ButtonOnClick(object sender,EventArgs e)

{

    this.Invoke(new Action(()=>

    {

        button.Text="关闭";

    }));

}

以上写法往往充斥着WinForm构建的程序。

在微软新一代的界面开发技术WPF中,由于界面呈现和业务逻辑原生态地分开在两个线程中,所以控件的事件响应函数就不必Invoke了。但是,如果手动开辟一个新线程,那么在这个新线程中改变控件的外观,则还是要Invoke的。

 

当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它,此时它将会在内部调用new MethodInvoker(LoadGlobalImage)来完成下面的步骤,这个做法保证了控件的安全,你可以这样理解,有人想找你借钱,他可以直接在你的钱包中拿,这样太不安全,因此必须让别人先要告诉你,你再从自己的钱包把钱拿出来借给别人,这样就安全了

 

 

another:

在设计中为了让界面与逻辑分离,我的做法是使用事件,界面只要响应事件来处理界面的显示就行了。而事件在逻辑处理中可能由不同的线程引发,这些事件的响应方法在修改界面中的控件内容时便会引发一个异常。

这时就用到了Control.InvokeRequired 属性 与Invoke方法。

MSDN中说:
获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。 
如果控件的 Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke 方法对控件进行调用),则为 true;否则为 false。
Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性 。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。该属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。

下面来说下这个的用法(我的一般做法):
首先定义一个委托,与这个事件处理函数的签名一样委托,当然直接使用该事件的委托也是可以的,如:

 private delegate void InvokeCallback( string msg);

然后就是判断这个属性的值来决定是否要调用Invoke函数:

 void m_comm_MessageEvent( string msg)
 {
 if (txtMessage.InvokeRequired)
 {
 InvokeCallbackmsgCallback = new InvokeCallback(m_comm_MessageEvent);
 txtMessage.Invoke(msgCallback, new object [] { msg } );
 } 
 else 
 {
 txtMessage.Text = msg;
 } 
 }

说明:这个函数就是事件处理函数,txtMessage是一个文本框。
这样就做到了窗体中控件的线程安全性。

 

------------------

InvokeRequired 当前线程不是创建控件的线程时为true
比如你可以自己开一个Thread,或使用Timer的事件来访问窗体上的控件的时候,在线程中窗体的这个属性就是True的。

简单的说,如果有两个线程,Thread A和Thread B,并且有一个Control c,是在Thread A里面new的。
那么在Thread A里面运行的任何方法调用c.InvokeRequired都会返回false。
相反,如果在Thread B里面运行的任何方法调用c.InvokeRequired都会返回true。
是否是UI线程与结果无关。(通常Control所在的线程是UI线程,但是可以有例外)

也可以认为,在new Control()的时候,control用一个变量记录下了当前线程,在调用InvokeRequired时,返回当前线程是否不等于new的时候记录下来的那个线程。

--------------------

我理解:如果InvokeRequired==true表示其它线程需要访问控件,那么调用invoke来转给控件owner处理。

原文链接:https://www.cnblogs.com/vaevvaev/p/6909042.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/538997.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Lock的tryLock(long time, TimeUnit unit)方法

概述 tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。…

python语音识别的第三方库_python标准库+内置函数+第三方库: 7.音频处理

python标准库内置函数第三方库 欲善其事,必先利其器 这其器必是python的标准库内置函数,话说许多第三方库, 也是对标准库的使用,进行封装,使得使用起来更方便。 这些库以使用场景来分类: 7、音频处理 音频处理主要适用…

SperingBoot+vue文件上传下载预览

上传文件: 前端: 整个过程,就是在使用FormData 添加 上File(这个Blob),并且key要和后台的名字对应上在点击上传按钮开始上传之前,使用了URL.createObjectURL(File)创建blobUrl,给了…

keepalived脑裂问题查找

在自己环境做keepalivedredis实验时&#xff0c;当重启了备用redies机器后&#xff0c;发现两台redies主机都拿到了VIP [plain] view plaincopy [rootredis2 ~]# ip addr list 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN link/loopbac…

python 多线程并行 矩阵乘法_python实现简单的并行矩阵乘法

python实现简单的并行矩阵乘法python实现简单的并行矩阵乘法本文采用的矩阵乘法方式是利用一个矩阵的行和二个矩阵的列相乘时不会互相影响。假设A(m,n)表示矩阵的m行&#xff0c;n列。那么C(m,m)A(m,n) * B(n,m) &#xff1a;计算C矩阵时候分解成&#xff1a;process-1&#xf…

停止Java线程,小心interrupt()方法

转自http://www.blogjava.NET/jinfeng_wang/archive/2008/04/27/196477.html ---------------------------------------------------------------------------------------------------- 程序是很简易的。然而&#xff0c;在编程人员面前&#xff0c;多线程呈现出了一组新的难…

python输入数学表达式并求值_用Python3实现表达式求值

一、题目描述 请用 python3编写一个计算器的控制台程序&#xff0c;支持加减乘除、乘方、括号、小数点&#xff0c;运算符优先级为括号>乘方>乘除>加减&#xff0c;同级别运算按照从左向右的顺序计算。 二、输入描述 数字包括"0123456789"&#xff0c;小数点…

mac上的mysql管理工具sequel pro

https://blog.csdn.net/wan_zaiyunduan/article/details/54909389 以前用过Plsql、Navicat、Workbench&#xff0c;现在换到mac上&#xff0c;用了现在这一款管理工具&#xff0c;很好用&#xff0c;所以推荐给大家。 完整的MySQL支持 Sequel Pro是一个快速,易于使用的Mac数据库…

报错 classes 拒绝访问_3种方式“移除”快速访问;为什么移除?你懂的...

Windows 10 在文件资源管理器中引入了"快速访问"这个功能&#xff0c;每当打开文件资源管理器窗口时&#xff0c;您都会看到常用文件夹和最近访问的文件的列表&#xff0c;这个功能虽然方便了日常使用&#xff0c;可能会提高工作效率&#xff0c;但是如果是公司的电脑…

java set是重复_java算法题,set内出现重复元素

题目将数字 1…9 填入一个33 的九宫格中&#xff0c;使得格子中每一横行和的值全部相等&#xff0c;每一竖列和的值全部相等。请你计算有多少种填数字的方案。这个是计蒜客上面的一个模拟题&#xff0c;我采用暴力。public class _3 {/** 将数字 1…9 填入一个33 的九宫格中&am…

Lock的lockInterruptibly()

概述 lockInterruptibly()方法比较特殊&#xff0c;当通过这个方法去获取锁时&#xff0c;如果其他线程正在等待获取锁&#xff0c;则这个线程能够响应中断&#xff0c;即中断线程的等待状态。也就使说&#xff0c;当两个线程同时通过lock.lockInterruptibly()想获取某个锁时&…

python中把输出结果写到一个文件中_Python3.6笔记之将程序运行结果输出到文件的方法...

Python3.6笔记之将程序运行结果输出到文件的方法 更新时间&#xff1a;2018年04月22日 14:27:32 投稿&#xff1a;jingxian 下面小编就为大家分享一篇Python3.6笔记之将程序运行结果输出到文件的方法&#xff0c;具有很好的参考价值&#xff0c;希望对大家有所帮助。一起跟随小…

hangfire.mysql.core_abp 使用 hangfire结合mysql

abp 官方使用的hangfire 默认使用的是sqlserver的存储mysql须要引入支持mysql的类库sql我这边使用的是Hangfire.MySql.Core数据库直接用nuget安装便可app首先按照官方文档要求&#xff0c;改几个地方sqlserver分别是 Startup 文件下serverservices.AddHangfire(config >{con…

python 图标题上移_Python-Matplotlib将图形标题移动到y轴

我目前在python中使用matplotlib来绘制一些数据,但是我希望图表的标题位于Y轴上,因为没有足够的空间来存储一个图形的标题和另一个图形的x轴标签.我知道我可以将hspace设置为更大的数字但是,我不想这样做,因为我计划将几个图表堆叠在一起,如果我调整hspace,那么图表将是真的简短…

solr的基础使用

查询运算符 例如&#xff1a;http://localhost:8984/solr/mycore/select?q*:* : 指定字段查指定值&#xff0c;如返回所有值q*:* ? 匹配单个字符&#xff0c; 例如: qtitle:??拳 可以匹配标题为“形意拳”的文档 * 匹配零个或多个字符, 例如: qtitle:*形意拳 或者 qtitl…

同步关键词lock

概述 1、API在JDK的java.util.concurrent.locks下。 2、不是Java关键字&#xff0c;是接口。 3、ReentrantLock是JDK唯一实现了Lock接口的类。 public interface Lock {//获取锁void lock();//可以响应中断的锁void lockInterruptibly() throws InterruptedException;//尝试…

Java bitset转string_将java BitSet保存到DB

默认情况下,JPA使用Java序列化来保存未知Serializable类型的属性(以便将序列化表示存储为byte []).通常它不是您想要的,因为可以有更有效的方式来表示您的数据.例如,BitSet可以有效地表示为数字(如果它的大小有界),或者byte [],或其他东西(遗憾的是,BitSet不提供进行这些转换的…

python读取raw图片文件_在python下读取并展示raw格式的图片实例

raw文件可能有些人没有&#xff0c;因此&#xff0c;先用一张图片创建一个raw格式的文件&#xff08;其实可以是其他类型的格式文件&#xff09; import numpy as np import cv2 img cv2.imread(cat.jpg) # 这里需要我们在当前目录下放一张名为cat.jpg的文件 img.tofile(cat.r…

python怎么网络通信_深入Python中的网络通信

TCP/IP计算机与网络设备两情侣要谈恋爱&#xff0c;相互通信&#xff0c;那么双方就必须有规则。基于相同的方法&#xff0c;不同的硬件、操作系统之间的通信&#xff0c;都需要一种规则。而我们就把这种规则称为协议(protocol)。TCP/IP 是互联网相关各类协议族的总称。TCP/IP是…

ReadWriteLock读写文件

概述 ReadWriteLock是一个接口&#xff0c;在它里面只定义了两个方法&#xff1a;一个读的锁和一个写的锁。 读的锁&#xff1a;A线程获取了读的锁&#xff0c;那么B线程也可以获取读的锁。 写的锁&#xff1a;A线程获取了写的锁&#xff0c;那么B线程不能获取读也不能获取写…