WPF:Window.Dispatcher调度的代码滞后执行的问

2019-02-15  本文已影响0人  hhp895

问题描述

在实现一个子线程进行网络文件下载,需要记录下载文件队列完成进度,以及每个文件下载进度。子线程中下载每一个文件是一个阻塞代码,也就是代码是在一个线程中往下执行,下载过程中需要向UI更新当前文件下载进度,使用进度条A表示,下载完毕后,要更新下载多个文件队列的进度,使用进度条B表示。
假设当前有3个文件需要下载,第一个文件下载完毕,进度条B就需要更新到1/3位置,进度条的更新代码是依靠Window.Dispatcher来执行的。

 this.Dispatcher.BeginInvoke(new Action(() => {
      //ui更新代码写在这里
 }));

整体代码结构如下:

new Thread(()=>{
for(int i=0;i<list.Count;i++)//list为下载队列
{  
    //下载....
    // ....
    //下载完毕
     this.Dispatcher.BeginInvoke(new Action(() => {
        //ui更新代码写在这里
        progressBar.value=i*1.0/list.Count*100;//问题:i总是不从0开始,而是从1开始,滞后一个
     }));
}
list.clear();
}).start();

分析

经过变量i的跟踪:

new Thread(()=>{
for(int i=0;i<list.Count;i++)//list为下载队列
{  
    //下载....
    // ....
    //下载完毕
    Console.WriteLine("i={0},list.Count={1}", i, list.Count);
     this.Dispatcher.BeginInvoke(new Action(() => {
        //ui更新代码写在这里
        Console.WriteLine("Dispatcher:i={0},list.Count={1}",i, list.Count);
        progressBar.value=i*1.0/list.Count*100;//问题:i总是不从0开始,而是从1开始,滞后一个
     }));
}
list.clear();
}).start();

发现日志输出:

i=0,list.Count=3
Dispatcher:i=1,list.Count=3
i=1,list.Count=3
Dispatcher:i=2,list.Count=3
i=2,list.Count=3
Dispatcher:i=1,list.Count=0

总是滞后于子线程执行。

解决

new Thread(()=>{
for(int i=0;i<list.Count;i++)//list为下载队列
{  
    //下载....
    // ....
    //下载完毕,更新进度
    int j=i;//复制一份i的值到j中,即使i变更了,也暂时不影响j
    int count=list.Count;
   //因为Dispatcher调度后的代码执行,不马上立即执行,会滞后,当执行调度后的代码时,i和list.Count的值已经发生了变化。
    Console.WriteLine("j={0},count={1}", j, count);
     this.Dispatcher.BeginInvoke(new Action(() => {
        //ui更新代码写在这里
        Console.WriteLine("Dispatcher:j={0},count={1}",j, count);
        progressBar.value=j*1.0/count*100;//问题:滞后执行,值变量赋值后得以解决。
     }));
}
list.Clear();
}).start();

日志输出:

j=0,count=3
Dispatcher:j=0,count=3
j=1,count=3
Dispatcher:j=1,count=3
j=2,count=3
Dispatcher:j=2,count=3
上一篇下一篇

猜你喜欢

热点阅读