问题
I'm quite new to WPF. I am developing a PRISM application and want to update the UI when an enumerable is updated.
I use a backgroundWorker in my modelView to update the enumaration. it all works fine until the enumeration it self gets updated and then the UI freezes!!
a friend told my I might be able to use the yield
keyword but I didn't quite figured it out.
Here is the code:
public void ChangeCollection()
{
BackgroundWorker worker = new BackgroundWorker();
// Set workers job
worker.DoWork += (sender, e) =>
{
RunOnUIThread(() => IsBusy = true);
e.Result = GetPrimes();
};
// On Complete
worker.RunWorkerCompleted += (sender, e) =>
{
RunOnUIThread(() =>
{
IsBusy = false;
// HERE IS WHERE IT GETS STUCK
Numbers = new ObservableCollection<int>
((IEnumerable<int>)e.Result);
});
};
// Start background operation
worker.RunWorkerAsync();
}
public ObservableCollection<int> Numbers
{
get {return _Numbers;}
set
{
_Numbers = value;
RaisePropertyChanged(() => Numbers);
}
}
public IEnumerable<int> GetPrimes()
{
List<int> primes = new List<int>();
for (int i = 0; i < 100000; i++)
{
bool IsPrime = true;
for (int j = 2; j < i; j++)
{
if (i % j == 0)
IsPrime = false;
}
if (IsPrime)
primes.Add(i);
}
return primes;
}
Any advise would be greatly appriciated!
Thanks, Omri
回答1:
A few things here. 1) Your worker and its delegates should be created when your object containing it is instantiated.
public class ViewModel
{
BackgroundWorker _primeWorker;
public ViewModel()
{
_primeWorker = new BackgroundWorker;
_primeWorker.DoWork += ...
}
public void AddSomeNumbers()
{
if(_primerWorker.IsBusy == false)
_primeWorker.RunWorkerAsync();
}
}
2) Your collection should be instantiated when the object containing it is instantiated to avoid a null exception being thrown should the object using this class calls the get
.
3) Adding that many items would cause slowness due to each time you add a number an event is fired that the UI thread has to handle.
This link has more info to help you out. http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
回答2:
yield
won't help you here. RunWorkerCompleted
executes on the UI thread. Apparently instantiating the ObservableCollection<int>
is taking a long time. The simplest solution may be to move the instantiation to the background thread (DoWork
) as well. It could also be a PropertyChanged
event handler that is taking a long time, in which case it should also run on a background thread.
来源:https://stackoverflow.com/questions/14526356/ui-still-freezes-using-backgroundworker