2011-01-21 81 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(); 
} 
相关问题