问题描述
自两天以来,我一直在尝试解决以下问题:我有一个WPF控件,其中WrapPanel绑定到ObservableCollection.一个动作会更改ObservableCollection的内容.内容被加载到BackgroundWorker中.在导致内容更改的操作之后,立即在foreach循环中需要新的内容.问题在于内容的加载速度很慢,因此需要一些准备工作.
since two days I am trying to solve the following problem:I have a WPF control where a WrapPanel is bound to an ObservableCollection. An action changes the content of the ObservableCollection. The content is loaded in a BackgroundWorker. Immediately after the action that caused the content change, the new content is needed in a foreach-loop. The problem is that the loading of the content is slow, so it needs a bit to get ready.
我的第一个尝试是等待后台工作,直到IsBusy属性设置为false.但是IsBusy属性在等待时从未改变!第二次尝试是尝试直接从BackgroundWorker操作ObservableCollection.当然没有成功,因为ObservableCollection位于BackgroundWorker之外的另一个线程中.
My first attempt was to wait for the backgroundworker until the IsBusy property is set to false. But the IsBusy property never changed while waiting!Second attempt was to try to manipulate the ObservableCollection directly from the BackgroundWorker. Of course no success because the ObservableCollection is in another thread than the BackgroundWorker.
我确实非常了解如何在跨线程范围内操作内容.但是他们都没有工作.已尝试使用Dispatcher,"ThreadSafeObservableCollection",.....
I read really really much about how to manipulate content in cross-thread-wide. But none of them worked. Tried solutions with Dispatcher, "ThreadSafeObservableCollection", .....
也许有人告诉我如何解决这个问题?有没有一种简单的方法可以在另一个线程中编辑UI线程的内容?还是我如何正确等待BackgroundWorker完成?
Might anyone tell me how I can solve that problem?Is there a simple way to edit content of the UI thread within another thread?Or how do I wait correctly for the BackgroundWorker to get finished?
但是如何等待BackgroundWorker完成呢?
But how can I wait for the BackgroundWorker to get finished???
推荐答案
BackgroundWorker可以通过两种方式为您提供帮助.
The BackgroundWorker can help you in two ways.
要在BGWorker运行时更新集合,请使用ProgressChanged
事件.此事件的名称具有误导性-您可以 更新任务的进度时,可以通过将对象传递给UI来将其实际用于需要在UI(调用)线程中完成的任何事情的ProgressChangedEventArgs的UserState属性.
To update the collection while the BGWorker is running, use the ProgressChanged
event. The name of this event is misleading - while you can update the progress of a task, you can use actually use it for anything that needs to be done in the UI (calling) thread by passing an object using the UserState property of the ProgressChangedEventArgs.
BGWorker完成时还会有一个事件.同样,您可以在RunWorkerCompleted
事件中的RunWorkerCompletedEventArgs的Result属性中将想要的任何信息传递回去.
The BGWorker also has an event when it finishes. Again, you can pass any information back to it that you'd like in the Result property of the RunWorkerCompletedEventArgs in the RunWorkerCompleted
event.
以下代码来自另一个线程关于BackgroundWorker的回答:
The following code is from another thread that I answered about 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();
}
这篇关于如何使用MVVM从BackgroundWorker内部更新ObservableCollection?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!