2011-08-31 97 views
1

我有一個來自wpf擴展工具包的BusyIndi​​cator,我正在運行需要一段時間才能完成的功能。如果我在一個單獨的線程中運行耗時的任務,我會得到一個NotSupportedException異常,因爲我試圖將對象從該不同的線程插入到ObservableCollection中。如果可能的話,我真的不想花太多時間重構代碼......有沒有一種方法可以將指標的可見性設置爲單獨的線程?在wpf應用程序中顯示busyindicator

編輯

ThreadStart start = delegate() 
    { 
     System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => 
      { 
       IsBusy = true; 
      })); 
    }; 

new Thread(start).Start();         
longRunningFunction(); 

這並沒有爲我工作,要麼。

+0

我編輯我的回答給您提供一個解決方案。 –

回答

1

你應該可以使用Dispatcher這樣的東西。例如

Application.Current.Dispatcher.Invoke((Action)(() => 
{ 
    _indicator.Visibility = Visibility.Visible; 
})); 

這將導致代碼在UI線程上運行。

threading model reference有更多的信息(包括如何「正確地」做到這一點,與CheckAccess等)。

+0

這不起作用...繁忙指示器不可見: 'System.Windows.Application.Current.Dispatcher.Invoke((Action)(()=> { IsBusy = true; }) ); functionThatTakesForever(); System.Windows.Application.Current.Dispatcher.Invoke((行動)(()=> { IsBusy = FALSE; }));' 將在事實上,我在視圖模型執行這些操作,而比代碼隱藏對它的行爲方式有什麼影響? – drowned

+0

@drowned:你在不同的線程上運行它,對吧?如果你不這樣做,用戶界面仍然會阻止。每當需要訪問UI線程擁有的元素(包括ObservableCollection)時,都可以在後臺線程中使用調度程序。 –

+0

也許我誤解了......我會更新我的問題以反映我試圖做的事情。 – drowned

0

您無法從後臺工作人員訪問UI控件。您通常在調用BackgroundWorker.RunWorkerAync()之前將IsBusy設置爲true,然後在BackgroundWorker.RunWorkerCompleted事件處理程序中將IsBusy設置爲false。 Seomthing像:

Backgroundworker worker = new BackgroundWorker(); 
worker.DoWork += ... 
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
{ 
    IsBusy = false; 
}; 
IsBusy = true; 
worker.RunWorkerAsync(); 

您可以使用調度程序將項目添加到您的ObservableCollection而在DoWork的事件hanlder。

編輯:這裏是完整的解決方案

 private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     //on UI thread 
     ObservableCollection<string> collection; 

     ThreadStart start = delegate() 
     { 
      List<string> items = new List<string>(); 
      for (int i = 0; i < 5000000; i++) 
      { 
       items.Add(String.Format("Item {0}", i)); 
      } 

      System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => 
      { 
       //propogate items to UI 
       collection = new ObservableCollection<string>(items); 
       //hide indicator 
       _indicator.IsBusy = false; 
      })); 
     }; 
     //show indicator before calling start 
     _indicator.IsBusy = true; 
     new Thread(start).Start();  
    } 
+0

雖然OP沒有提及BackgroundWorker的使用...... –

+0

這是我嘗試的第一件事。嘗試插入集合時遇到相同的異常。 – drowned

+0

@ H.B。即使您不使用BackgroundWorker,概念也是一樣的。 –