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

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

  1. 安卓手机更新过程手机乱码_王者荣耀安卓更新更新时出现乱码解决办法

    王者荣耀1月14日进行版本大更新了,一般情况下大版本更新容易出问题的是苹果,但这次反过来是安卓,包括更新卡在45%.资源包升级失败.解析包出现问题等情况,这些都如何解决呢?小编马上就给大家分享一下解决 ...

  2. 说说百度快照不更新的原因及解决办法

    百度快照是什么?有什么用呢?快照是指搜索引擎蜘蛛抓取后在其数据库内建立的备份,这样做的好处是为了当你的网站打不开时,用户可以通过快照来查看网站内容.下面合肥seo我们看网站快照时间的位置. 今天讲解关 ...

  3. hive数据倾斜的解决办法

    数据倾斜是进行大数据计算时常见的问题.主要分为map端倾斜和reduce端倾斜,map端倾斜主要是因为输入文件大小不均匀导致,reduce端主要是partition不均匀导致. 在hive中遇到数据倾 ...

  4. steam游戏一直连接服务器,steam无法连接到更新服务器快速有效解决办法

    <steam>是玩家们使用较多的一个游戏平台,部分玩家启动过程中会出现无法连接的情况,于是就会发出steam无法连接到更新服务器怎么办的疑问.下面为大家带来的是steam无法连接到更新服务 ...

  5. layui数据表格中导出所有数据的简易解决办法

    layui数据表格中导出所有数据的简易解决办法 官方文档的困惑 解决办法 官方文档的困惑 首先要说明的是:layui在 table 的工具栏内置了数据导出按钮,如果你是用它内置的导出按钮来导出数据,是 ...

  6. EPIC客户端 “在我们启动更新时请稍后”解决办法

    EPIC客户端 "在我们启动更新时请稍后"解决办法 已经尝试的方法:使用各种 加速器 标题解决问题的方法: 实例:

  7. C# System.IO.IOException HResult=0x8007000D Message=数据无效。解决办法

    C# System.IO.IOException HResult=0x8007000D Message=数据无效.解决办法 HResult=0x8007000D Message=数据无效.解决办法) ...

  8. 百度首页打不开_SEO百度快照不更新原因,以及解决办法

    最让SEO新手们纠结不已的快照问题,就是快照迟迟不更新,甚至很多网站还出现了快照倒退的现象,原本这没有什么好惊慌的,但是偏偏网站的排名一直不良好,SEOer就开始纠结了,然后到处找方法,目的只有一个, ...

  9. 使用AFNetworking请求新浪微博数据接口出错解决办法

    在使用AFNetworking请求新浪微博数据接口时会出这样的错误,如 这样的错误说明,AFNetworking无法处理这样的数据格式.所以,我们需要修改AFNetworking中的一些接收数据格式. ...

最新文章

  1. [LeetCode226]Invert Binary Tree
  2. Little Sub and Counting
  3. 常见排序算法之冒泡排序
  4. centos7镜像加速_docker 镜像加速CentOS7详细介绍
  5. 基础知识回顾——通用序列操作
  6. Django2.1简介及安装
  7. 你知道Arrays.asList 有坑吗?千万别踩啊!
  8. bootstrap中关于兼容ie8 和 rem的问题总结
  9. 线程同步机制的区别与比较及进程通信方法
  10. 关于过程改进和能力提升
  11. 最速下降法python_算法最优化之最速下降法
  12. 软件测试中报表测试用例设计方法总结
  13. 谷歌地图api的使用 一
  14. 软件项目规划大纲知识点
  15. Dubbo Cloud Native 实践与思考 1
  16. 制作openstack镜像win7.qcow2(centos/ubuntu/win镜像分享)
  17. RPC 框架 Kitex 初体验 (虚拟机环境)
  18. 简历快投啊!!!!!!!!!!!!!!!(转自水木)
  19. NETPLIER : 一款基于概率的网络协议逆向工具(一)理论
  20. apple iMac一体机 装双系统 实战! (Apple +Win 7 64bit)

热门文章

  1. (作者:无名`)svn提交代码到本地仓库
  2. BugkuCTF-MISC题红绿灯
  3. matlab保存并关闭excel文件夹,[转载]Matlab批量操作目标文件夹下的Excel文件
  4. c web mysql数据库_C连接Mysql数据库代码
  5. java非递归_Java非递归文件系统走路
  6. 银联分账与银联代付_第三方分账系统到底有哪些作用?
  7. 图书管理系统 java 源码_[源码和文档分享]基于C语言和SQL SERVER数据库实现的图书管理系统...
  8. 清华大学计算机系高考生源,清华大学在这个高考大省录取人数创新高,网友:仍然是同分不同命...
  9. mvc mysql linq_MVC3+Linq to sql 显示数据库中数据表的数据
  10. linux添加源地址ping,实战经验:Linux Source NAT在Ping场景下的应用