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.pswp.cn/news/538997.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/538997.shtml
英文地址,請注明出處:http://en.pswp.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線程不能獲取讀也不能獲取寫…