2015-08-27 58 views
-1

在我的XML编辑器中,我希望能够使用索引文件一次打开多个文件。显然,根据文件数量的不同,这可能需要一些时间,我想使用进度条来通知用户程序仍在加载并执行某些操作。 从我研究的方式来保持UI进度栏更新使用BackgroundWorker。如何让BackgroundWorker阻止UI线程?

public MainWindow() 
     { 
      InitializeComponent(); 

      tabList = new ObservableCollection<FileTab>(); 

      tabControl.ItemsSource = tabList; 

      backgroundWorker = new BackgroundWorker(); 
      backgroundWorker.DoWork += backgroundWorker_DoWork; 
      backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged; 
      backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted; 
      backgroundWorker.WorkerReportsProgress = true; 
     } 

(...) 

private void OpenProjectButtonClick(object sender, RoutedEventArgs e) 
     { 
      openingProgressBar.Value = 0; 
      openingProgressBar.Visibility = System.Windows.Visibility.Visible; 
      backgroundWorker.RunWorkerAsync(); 
     } 

void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
     { 
      int i = 0; 
      foreach (IndexFile file in indexManager.fileList) 
      { 
       this.Dispatcher.Invoke((Action)(() => 
        { 
         tabList.Add(new FileTab(file.filePath)); 
        })); 
       i++; 
       Console.WriteLine("-(DoWork)->" + i); 
       double percentage = (Convert.ToDouble(i)/Convert.ToDouble(indexManager.fileList.Count)) * 100; 
       Console.WriteLine("-(DoWork.percentage)-> "+ percentage); 
       backgroundWorker.ReportProgress((int)percentage); 
      } 
     } 
void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      openingProgressBar.Value = e.ProgressPercentage; 
      Console.WriteLine("-(ProgressChanged)->" + openingProgressBar.Value); 
     } 
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      openingProgressBar.Visibility = System.Windows.Visibility.Collapsed; 
      backgroundWorker.Dispose(); 
      Console.WriteLine("-(RunWorkerComplete)-> Done"); 
     } 

由于我访问的DoWork的法的标签列表我包裹在Dispathcer.Invoke这一呼吁。在这种形式下,代码类型做我想要的。它使折叠的progressBar可见并每隔一段时间更新一次。可悲的是,它不会在每次加载文件后更新百分比。从控制台中可以看到,ProgressChanged执行滞后于DoWork。根据我的理解,它在循环的每个迭代中都被调用。即使它触发了,用户界面并不总是对此作出响应。

所以我的问题是:我仍然阻止UI线程以及我怎么修复它?

回答

0

的问题是,

你做UI和BackgroundWorker之间的耦合

上ReportProgress解决方案

回报您的FileTab对象

void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    int i = 0; 
    foreach (IndexFile file in indexManager.fileList) 
    { 
     i++; 
     Console.WriteLine("-(DoWork)->" + i); 
     double percentage = (Convert.ToDouble(i)/Convert.ToDouble(indexManager.fileList.Count)) * 100; 
     Console.WriteLine("-(DoWork.percentage)-> "+ percentage); 
     backgroundWorker.ReportProgress((int)percentage,new FileTab(file.filePath)); 
    } 
} 

然后在backgroundWorker_ProgressChanged添加FileTab对象到tabList

+0

这工作,现在它是如此之快,我几乎不再需要进度条了......谢谢! – Ultus

+0

不幸的是没有为我工作。我正在报告当前循环'i',并在报告事件中将此int设置为名为'ProgressValue'的属性。这个'ProgressValue'作为值绑定到进度条。我的用户界面仍然阻塞。 – C4u

+0

@ C4u那么改变那个怎么样? (我看不到你的问题)。在“DoWork”中执行你的工作(所有的值必须是来自你的用户界面的自治),并且每次你完成一个部分时,通过ReportProgress将它报告给你的用户界面威胁(在这里你可以使用UI值(比如'ProgressValue')如果你需要在你的UI中再做一些事情,那么当你所有的工作完成时调用'RunWorkerCompleted',我希望这会帮助你:-) – WiiMaxx

0

尝试移动报告进度操作在调度程序的操作:

foreach (IndexFile file in indexManager.fileList) 
      { 
       this.Dispatcher.Invoke((Action)(() => 
        { 
         tabList.Add(new FileTab(file.filePath)); 
         Console.WriteLine("-(DoWork)->" + i); 
         double percentage = (Convert.ToDouble(i)/Convert.ToDouble(indexManager.fileList.Count)) * 100; 
         Console.WriteLine("-(DoWork.percentage)-> "+ percentage); 
         backgroundWorker.ReportProgress((int)percentage); 
        })); 
       i++; 

      } 

这有可能是在另一个线程调度运行...

+0

可悲的是,这似乎并没有改变行为。 – Ultus