2011-01-21 17 views
5

,因爲這兩天我正試圖解決以下問題: 我有一個地方是WrapPanel綁定到一個ObservableCollection WPF控件。一個動作改變了ObservableCollection的內容。內容被加載到BackgroundWorker中。在導致內容更改的操作之後立即在foreach循環中需要新內容。問題是內容的加載速度很慢,所以需要一點準備。如何使用MVVM從BackgroundWorker內部更新ObservableCollection?

我第一次嘗試是等待的BackgroundWorker直到IsBusy屬性設置爲false。但IsBusy屬性在等待時從未改變! 第二次嘗試是嘗試直接從BackgroundWorker操作ObservableCollection。當然,因爲ObservableCollection位於BackgroundWorker之外的另一個線程中,所以沒有成功。

我看了真的很瞭解如何操縱跨線程範圍的內容。但他們都沒有工作。與調度員試圖解決方案,「ThreadSafeObservableCollection」,...

也許有人告訴我,我該怎麼解決這個問題? 有沒有簡單的方法來編輯另一個線程內的UI線程的內容? 或者如何正確等待BackgroundWorker完成?

編輯: 但我如何等待BackgroundWorker完成?

回答

4

ObservableCollection.Add到UI線程應該工作的調度。

App.Current.Dispatcher.Invoke(new Action(() => collection.Add(item))); 
+0

這並沒有節省時間的幫助下,它運行,但在相同的線程! – 2011-06-24 09:07:01

1

BackGroundWorker完成時觸發事件。 我已經在類似的情況已經做的是:

我有一個名單,是不是一個observablecollecion啓用

  • 套裝=在我的窗口虛假,並顯示一個微調
  • 開始後臺工作
  • 在我的DoWork填充列表
  • 在RunWorkerCompleted事件
  • 我的列表內容複製到我的ObservableCollection並啓用的東西,隱藏微調

所以與集合的所有交互都在同一個線程上 - 複製通常不是昂貴的部分。

2

您可以在BackgroundWorker.RunWorkerCompleted事件處理程序中更新您的集合。它運行在你開始的同步上下文中,這是一個UI線程,通常你可以安全地使用任何UI相關的東西。

8

BackgroundWorker可以通過兩種方式來幫助你。

若要在BGWorker運行更新集合,使用ProgressChanged事件。這個事件的名稱是誤導性的 - 雖然你可以更新任務的進度,你可以使用它的任何需要在UI(調用)線程完成的任何事情,通過傳遞一個對象使用UserState屬性的ProgressChangedEventArgs。

BGWorker完成時還有一個事件。同樣,你可以在任何信息傳回給它,你會在RunWorkerCompletedEventArgs在RunWorkerCompleted事件Result屬性一樣。

下面的代碼是從another thread,我回答了有關的BackgroundWorker:

BackgroundWorker bgWorker = new BackgroundWorker(); 
ObservableCollection<int> mNumbers = new ObservableCollection<int>(); 

public Window1() 
{ 
    InitializeComponent(); 
    bgWorker.DoWork += 
     new DoWorkEventHandler(bgWorker_DoWork); 
    bgWorker.ProgressChanged += 
     new ProgressChangedEventHandler(bgWorker_ProgressChanged); 
    bgWorker.RunWorkerCompleted += 
     new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); 
    bgWorker.WorkerReportsProgress = true; 

    btnGenerateNumbers.Click += (s, e) => UpdateNumbers(); 

    this.DataContext = this; 
} 

void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    progress.Visibility = Visibility.Collapsed; 
    lstItems.Opacity = 1d; 
    btnGenerateNumbers.IsEnabled = true; 
} 

void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    List<int> numbers = (List<int>)e.UserState; 
    foreach (int number in numbers) 
    { 
     mNumbers.Add(number); 
    } 

    progress.Value = e.ProgressPercentage; 
} 

void bgWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Random rnd = new Random(); 
    List<int> numbers = new List<int>(10); 

    for (int i = 1; i <= 100; i++) 
    { 
     // Add a random number 
     numbers.Add(rnd.Next());    

     // Sleep from 1/8 of a second to 1 second 
     Thread.Sleep(rnd.Next(125, 1000)); 

     // Every 10 iterations, report progress 
     if ((i % 10) == 0) 
     { 
      bgWorker.ReportProgress(i, numbers.ToList<int>()); 
      numbers.Clear(); 
     } 
    } 
} 

public ObservableCollection<int> NumberItems 
{ 
    get { return mNumbers; } 
} 

private void UpdateNumbers() 
{ 
    btnGenerateNumbers.IsEnabled = false; 
    mNumbers.Clear(); 
    progress.Value = 0; 
    progress.Visibility = Visibility.Visible; 
    lstItems.Opacity = 0.5; 

    bgWorker.RunWorkerAsync(); 
} 
相關問題