美文网首页C#/C++/C
WPF中UI线程频繁操作造成卡顿的处理(一)

WPF中UI线程频繁操作造成卡顿的处理(一)

作者: hhp895 | 来源:发表于2017-07-17 15:33 被阅读0次

    转载请注明原作者

    目录

    WPF中UI线程频繁操作造成卡顿的处理(一)
    WPF中UI线程频繁操作造成卡顿的处理(二)

    问题描述

    有些时候,在项目开发中可能需要在某一很短时间内频繁操作UI控件,如以循环方式中瞬间向UI界面上添加1000张图片。这个任务场景有2个特点:
    (1)所完成的任务是耗时任务——要频繁读取图片和加载图片。
    (2)加载图片是UI操作,无法在非UI线程中完成。

    解决办法:

    能否每加载一个图片更新一下UI界面?而不是1000张图片读取完毕后一次性附加到界面上显示。

    预备知识:

    (1)WPF中Invoke和BeginInvoke方法,参考链接:http://www.cnblogs.com/Z-King/archive/2011/11/03/2234337.html
    (2)Dispatcher的认识,参考链接:http://blog.csdn.net/albert528108/article/details/51503955
    (3)DispatcherPriority的认识,参考链接:https://msdn.microsoft.com/zh-cn/library/system.windows.threading.dispatcherpriority.aspx
    (4)依赖属性、INotifyPropertyChanged、ObservableCollection相关知识。

    分析:

    (1)所有UI的操作必须在UI线程上进行,无法在子线程中进行。
    (2)线程上的操作又由Dispatcher分为不同的优先级。如果不希望UI上出现卡顿的情况,就必须将UI线程的图片加载(render)操作的优先级别降到UI线程上输入(input)操作的优先级之下。也就是input操作优先于图片呈现,界面就不会出现卡死状态。
    (3)所有操作必须异步进行,这样不会堵塞线程。为了不让1000张图片同时加载到界面上,这里逐步调用BeginInvoke方法,每一次只比上一次多加载一张图片。何时终止,采用递归方式反复调用直到读完图片为止。

    做法一:

    未逐步加载,一次加载图片的做法。代码:

           private void Btn_Click(object sender, RoutedEventArgs e)
           {
                  strings = loadDir(@"G:\BaiduYunDownload\风景图片壁纸\风景图片壁纸100张");
              
                  lb.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
                 {
                         lb.ItemsSource = loadDir(@"G:\BaiduYunDownload\风景图片壁纸\风景图片壁纸100张");
                 }));
          }
    

    效果图如下:


    有卡顿

    所有图片明显一次性出现,按钮点击后直接卡住。等所有图片都出现后,按钮的卡住状态恢复正常。

    做法二:

    图片一张张逐步加载,每次多增加一张图片。代码:

            int i;
            List<String> strings;
            ObservableCollection<String> strs = new ObservableCollection<string>();
            private void Btn_Click(object sender, RoutedEventArgs e)
            {
                strings = loadDir(@"G:\BaiduYunDownload\风景图片壁纸\风景图片壁纸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;
            }
    

    效果图如下:

    无卡顿

    图片逐步加载,每次比上次多增加一张。按钮点击后立即恢复原来状态,UI无卡顿。

    目录

    WPF中UI线程频繁操作造成卡顿的处理(一)
    WPF中UI线程频繁操作造成卡顿的处理(二)

    相关文章

      网友评论

        本文标题:WPF中UI线程频繁操作造成卡顿的处理(一)

        本文链接:https://www.haomeiwen.com/subject/wyzfkxtx.html