日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

c#winform控件过多卡顿问题解决方案

發(fā)布時(shí)間:2023/12/18 C# 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c#winform控件过多卡顿问题解决方案 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

近期在項(xiàng)目中遇到了登錄以及切換界面時(shí),界面不停閃爍的問(wèn)題,經(jīng)過(guò)查閱發(fā)現(xiàn)以下方法可以成功解決該問(wèn)題。

將下面代碼添加到窗體代碼中即可:

  • protected override CreateParams CreateParams //防止界面閃爍

  • {

  • get

  • {

  • CreateParams paras = base.CreateParams;

  • paras.ExStyle |= 0x02000000;

  • return paras;

  • }

  • }

  • 一、通過(guò)對(duì)窗體和控件使用雙緩沖來(lái)減少圖形閃爍(當(dāng)繪制圖片時(shí)出現(xiàn)閃爍時(shí),使用雙緩沖)

    對(duì)于大多數(shù)應(yīng)用程序,.NET Framework 提供的默認(rèn)雙緩沖將提供最佳效果。默認(rèn)情況下,標(biāo)準(zhǔn) Windows 窗體控件是雙緩沖的。可以通過(guò)兩種方法對(duì)窗體和所創(chuàng)作的控件啟用默認(rèn)雙緩沖。一種方法是將 DoubleBuffered 屬性設(shè)置為 true,另一種方法是通過(guò)調(diào)用 SetStyle 方法將 OptimizedDoubleBuffer 標(biāo)志設(shè)置為 true。兩種方法都將為窗體或控件啟用默認(rèn)雙緩沖并提供無(wú)閃爍的圖形呈現(xiàn)。建議僅對(duì)已為其編寫所有呈現(xiàn)代碼的自定義控件調(diào)用 SetStyle 方法。

    在構(gòu)造函數(shù)里加上以下代碼:

    1 this.DoubleBuffered = true;//設(shè)置本窗體 2 SetStyle(ControlStyles.UserPaint, true); 3 SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景. 4 SetStyle(ControlStyles.DoubleBuffer, true); // 雙緩沖 5 //SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); 6 7 //UpdateStyles();

    ?

    二、C#控件的閃爍問(wèn)題解決方法總結(jié)
    最近對(duì)代碼作了一些優(yōu)化,試驗(yàn)后效果還可以,但是發(fā)現(xiàn)界面會(huì)閃爍,具體是TreeView控件會(huì)閃爍,語(yǔ)言為C#,IDE為VS2005。在查閱一些資料,使用了一些基本技術(shù)后(如開(kāi)啟雙緩沖),發(fā)現(xiàn)沒(méi)什么效果。
    ? ? ? ? 于是使用Profiler工具,查找出瓶頸在于每次更新完界面的EndUpdate操作(使用這個(gè)是為了減少界面更新次數(shù),但這里不理想是因?yàn)榭丶兄械脑睾芏?#xff09;,猜想大概每次更新,.Net底層都會(huì)更新重繪每個(gè)圖元,所以速度會(huì)慢,造成閃爍。但是如果這樣,使用雙緩沖應(yīng)該會(huì)有較好效果。再看代碼,發(fā)現(xiàn)可能是更新動(dòng)作太過(guò)頻繁,于是降低速度,有所好轉(zhuǎn),但還是不行。
    ? ? ? ?繼續(xù)在網(wǎng)上查閱,最終找到一個(gè)方案比較合適。原來(lái)底層重繪每次會(huì)清除畫布,然后再全部重新繪制,這才是導(dǎo)致閃爍最主要的原因。于是重載消息發(fā)送函數(shù)操作,禁掉這條消息。代碼如下:

    1 protected override void WndProc(ref Message m) 2 { 3 if (m.Msg == 0x0014) // 禁掉清除背景消息 4 return; 5 base.WndProc(ref m); 6 }

    成功!

    ?

    注:雙緩沖還是有用的,在更新不是很頻繁且控件內(nèi)含元素不是特別多的時(shí)候。一旦元素過(guò)多,每次更新時(shí)間都比較長(zhǎng),即便使用了雙緩沖,仍解決不了閃爍問(wèn)題。個(gè)人認(rèn)為最終比較理想的方法還是禁掉清除背景消息。


    附:一些嘗試過(guò)但失敗的記錄
    1)使用setStyle
    ? ? ? 網(wǎng)上有說(shuō)使用setStyle函數(shù)去設(shè)置該控件的參數(shù),具體為:
    ? ? ? SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
    ? ? ? 這三個(gè)選項(xiàng)參數(shù)后者是依賴前者的,必須并存,否則無(wú)效。并且這個(gè)函數(shù)本身是protected的,所以首先需要繼承某控件再使用。
    ? ? ? 這個(gè)目標(biāo)是跟前面正確解決方案一致,也是禁止清除背景并開(kāi)啟雙緩沖,但需要使用用戶繪制選項(xiàng),而且是全部交由用戶繪制。這需要自己實(shí)現(xiàn)控件的全部繪制,比較麻煩。所以這個(gè)方法不是完全不可行,但是需要額外工作量,不推薦。我也沒(méi)有使用。


    2)使用BeginUpdate和EndUpdate
    ? ? ? 這一對(duì)操作對(duì)于需要批量操作更新控件的情景有比較好的效果,比如初始化時(shí)批量添加了大量節(jié)點(diǎn)。壞處就在于不能即時(shí)更新。所以,對(duì)于頻繁的更新節(jié)點(diǎn)并希望立即反映到界面的情況不適用。如果使用并且沒(méi)有禁掉清除界面消息的話,則控件看起來(lái)就會(huì)不停的閃爍,而且以白底為主,內(nèi)容幾乎不可見(jiàn)(這個(gè)視頻繁程度而定)。因?yàn)榻缑娓露荚贓ndUpdate處完成,操作太多導(dǎo)致EndUpdate阻塞時(shí)間過(guò)長(zhǎng),且清空在先,更新在后,導(dǎo)致界面看起來(lái)長(zhǎng)時(shí)間處于空白狀態(tài)。


    3)使用ControlStyles.EnableNotifyMessage選項(xiàng)
    ? ? ? 這個(gè)選項(xiàng)的作用和正確解決方案也是一致的。使用方法是:
    ? ? ? SetStyle(ControlStyles.EnableNotifyMessage, true);
    ? ? ? protected override void onNotifyMessage(Message m)
    ? ? ? {
    ? ? ? ? ? ? ? ?// 此處書寫過(guò)濾消息代碼
    ? ? ? }
    ? ? ? 但是實(shí)際實(shí)驗(yàn)顯示無(wú)效果,不知是什么原因,沒(méi)有細(xì)究。

    ?

    三、個(gè)人在一個(gè)winfrom中測(cè)試?yán)胻imer控件對(duì)要刷新的控件進(jìn)行定時(shí)刷新,可能也能起到作用。

    ?

    四、C# winform 局部刷新
    做winform界面程序時(shí),經(jīng)常會(huì)遇到后臺(tái)處理占用大量時(shí)間的情況,這就會(huì)造成界面假死狀態(tài)。一般解決界面假死有兩種方式:要么把占用大量時(shí)間的處理方式放入其他線程;要么把界面顯示放入其他線程。第一種方式應(yīng)該比較簡(jiǎn)單,開(kāi)單獨(dú)的線程,處理數(shù)據(jù),將處理數(shù)據(jù)顯示到界面就好。但是我們經(jīng)常需要在主程序運(yùn)算一些內(nèi)容,否則可能會(huì)改動(dòng)比較大。因此,這里講講第二種方式。
    同樣是使用多線程,但是c#在其他線程刷新有一點(diǎn)點(diǎn)問(wèn)題,即不能跨線程操作界面。這可以使用控件的Invoke方法解決:

    1 private delegate void CrossThread(); 2 Control control = ....; 3 CrossThread cross = delegate() 4 { 5 control.Refresh(); 6 }; 7 control.Invoke(cross);

    這樣可以讓控件在其它線程刷新界面。


    再加上開(kāi)新線程后的通用方法:

    1 private void InvaliateControl(Control control)2 {3 Thread t = new Thread(4 new ThreadStart(delegate()5 {6 CrossThread cross = delegate()7 {8 control.Refresh();9 }; 10 control.Invoke(cross); 11 } 12 )); 13 }

    這樣就可以在任何時(shí)候,調(diào)用此方法對(duì)控件進(jìn)行刷新,而不將整個(gè)界面刷新。如果對(duì)于同一個(gè)控件,連續(xù)多次刷新,可以添加一個(gè)成員變量作為標(biāo)記,以免同一控件連續(xù)多次刷新,提升部分性能。


    補(bǔ)充:在主線程調(diào)用耗時(shí)操作用此方法可能會(huì)有問(wèn)題,經(jīng)過(guò)驗(yàn)證調(diào)用Invoke函數(shù),其實(shí)是在主線程刷新界面。

    總結(jié)

    以上是生活随笔為你收集整理的c#winform控件过多卡顿问题解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲一区二区三区香蕉 | 日韩视频在线免费播放 | 精品日韩一区二区 | 日韩精品乱码 | 亚洲一二三视频 | 嫩草影院永久入口 | 欧美麻豆 | 国产区一区二区三 | 色97| 天天草比 | 免费啪啪小视频 | 欧美日韩另类在线 | 色屁屁一区二区 | 九九热国产在线 | 亚洲深夜在线 | 欧色图 | 中文字幕亚洲乱码熟女1区2区 | 88久久精品无码一区二区毛片 | 人妻熟女一区二区三区app下载 | 久久精品2019中文字幕 | 另类小说婷婷 | 2025韩国大尺度电影 | missav|免费高清av在线看 | 亚洲精品久久久久国产 | 亚洲日本久久 | 精品久久a | 中文字幕无码人妻少妇免费 | 久草网视频在线观看 | 少妇 av | 中文字幕国产在线观看 | 床上激情网站 | 日韩在线观看视频一区二区 | 亚洲无av| 欧美卡一卡二 | 精品少妇视频 | 91在现看 | 国产精品一区二区人妻喷水 | 久草免费在线视频 | 色婷婷九月 | 欧洲美熟女乱又伦 | www.四虎在线观看 | 国产视频久久久久久久 | 日韩网站免费 | 18无码粉嫩小泬无套在线观看 | 我们2018在线观看免费版高清 | 国产精品一级片在线观看 | 草草在线视频 | 午夜免费成人 | 不卡中文av | 韩国三级视频 | 999国产 | 日韩无砖| 亚洲人在线视频 | 爱爱一级 | 99在线无码精品入口 | 极品三级 | 男女互操在线观看 | 杨贵妃颤抖双乳呻吟求欢小说 | 中文在线免费看视频 | 日韩在线专区 | 久久超碰av | 极品美女扒开粉嫩小泬 | 中文字幕欲求不满 | 欧美一区二区三区的 | 亚洲妇女av| 97超碰国产精品无码蜜芽 | 美女av片 | 二十四小时在线更新观看 | 亚洲一线av | 影音先锋中文在线 | 一级黄色片网站 | 黄色麻豆视频 | h片免费网站 | 国产精品三级av | 99福利在线 | 美女免费网站 | 精品一区二区三区四区 | 欧美日韩h | 国产成人av片 | 国产精品毛片久久久久久 | 天天狠狠干 | 自拍一级片 | 伊人网视频在线 | 狠狠澡| 蘑菇福利视频一区播放 | 一级毛片黄片 | 日韩激情小视频 | 涩涩涩涩涩涩涩涩涩涩 | 福利视频99 | 成人试看120秒体验区 | 欧美综合一区二区 | 超碰在线播放97 | 2020av视频 | 国产小视频在线免费观看 | 国产精品成人在线 | 先锋影音在线 | 色多多视频在线观看 | 久久精品在线视频 | 亚洲最大综合网 |