2015-08-27 87 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