WPF中UI線程頻繁操作造成卡頓的處理(一)

轉(zhuǎn)載請(qǐng)注明原作者

目錄

WPF中UI線程頻繁操作造成卡頓的處理(一)
WPF中UI線程頻繁操作造成卡頓的處理(二)

問題描述

有些時(shí)候,在項(xiàng)目開發(fā)中可能需要在某一很短時(shí)間內(nèi)頻繁操作UI控件,如以循環(huán)方式中瞬間向UI界面上添加1000張圖片。這個(gè)任務(wù)場(chǎng)景有2個(gè)特點(diǎn):
(1)所完成的任務(wù)是耗時(shí)任務(wù)——要頻繁讀取圖片和加載圖片。
(2)加載圖片是UI操作,無法在非UI線程中完成。

解決辦法:

能否每加載一個(gè)圖片更新一下UI界面?而不是1000張圖片讀取完畢后一次性附加到界面上顯示。

預(yù)備知識(shí):

(1)WPF中Invoke和BeginInvoke方法,參考鏈接:http://www.cnblogs.com/Z-King/archive/2011/11/03/2234337.html
(2)Dispatcher的認(rèn)識(shí),參考鏈接:http://blog.csdn.net/albert528108/article/details/51503955
(3)DispatcherPriority的認(rèn)識(shí),參考鏈接:https://msdn.microsoft.com/zh-cn/library/system.windows.threading.dispatcherpriority.aspx
(4)依賴屬性、INotifyPropertyChanged、ObservableCollection相關(guān)知識(shí)。

分析:

(1)所有UI的操作必須在UI線程上進(jìn)行,無法在子線程中進(jìn)行。
(2)線程上的操作又由Dispatcher分為不同的優(yōu)先級(jí)。如果不希望UI上出現(xiàn)卡頓的情況,就必須將UI線程的圖片加載(render)操作的優(yōu)先級(jí)別降到UI線程上輸入(input)操作的優(yōu)先級(jí)之下。也就是input操作優(yōu)先于圖片呈現(xiàn),界面就不會(huì)出現(xiàn)卡死狀態(tài)。
(3)所有操作必須異步進(jìn)行,這樣不會(huì)堵塞線程。為了不讓1000張圖片同時(shí)加載到界面上,這里逐步調(diào)用BeginInvoke方法,每一次只比上一次多加載一張圖片。何時(shí)終止,采用遞歸方式反復(fù)調(diào)用直到讀完圖片為止。

做法一:

未逐步加載,一次加載圖片的做法。代碼:

       private void Btn_Click(object sender, RoutedEventArgs e)
       {
              strings = loadDir(@"G:\BaiduYunDownload\風(fēng)景圖片壁紙\風(fēng)景圖片壁紙100張");
          
              lb.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
             {
                     lb.ItemsSource = loadDir(@"G:\BaiduYunDownload\風(fēng)景圖片壁紙\風(fēng)景圖片壁紙100張");
             }));
      }

效果圖如下:


有卡頓

所有圖片明顯一次性出現(xiàn),按鈕點(diǎn)擊后直接卡住。等所有圖片都出現(xiàn)后,按鈕的卡住狀態(tài)恢復(fù)正常。

做法二:

圖片一張張逐步加載,每次多增加一張圖片。代碼:

        int i;
        List<String> strings;
        ObservableCollection<String> strs = new ObservableCollection<string>();
        private void Btn_Click(object sender, RoutedEventArgs e)
        {
            strings = loadDir(@"G:\BaiduYunDownload\風(fēng)景圖片壁紙\風(fēng)景圖片壁紙100張");
            strs.Clear();
            i = 0;
            lb.ItemsSource = strs;
            lb.Dispatcher.BeginInvoke(DispatcherPriority.Background, new AddItemDelegate(addItem));
        }
   
        private delegate void AddItemDelegate();
        private void addItem()
        {
            if (i < strings.Count)
            {
                strs.Add(strings[i++]);
                lb.Dispatcher.BeginInvoke(DispatcherPriority.Background,new AddItemDelegate(addItem));
            }
        }

        private List<String> loadDir(string dirpath)
        {
            List<String> strs = new List<string>();
            if (Directory.Exists(dirpath))
            {

                foreach (var item in new DirectoryInfo(dirpath).GetFiles("*.jpg"))
                {
                    strs.Add(item.FullName);
                }
            }
            return strs;
        }

效果圖如下:

無卡頓

圖片逐步加載,每次比上次多增加一張。按鈕點(diǎn)擊后立即恢復(fù)原來狀態(tài),UI無卡頓。

目錄

WPF中UI線程頻繁操作造成卡頓的處理(一)
WPF中UI線程頻繁操作造成卡頓的處理(二)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容