我对WPF很新。我正在开发一个PRISM应用程序,并希望在更新可枚举时更新UI。
我在modelView中使用backgroundWorker来更新enumaration。它一切正常,直到它自我更新的枚举,然后UI冻结!
一位朋友告诉我,我可能可以使用yield
关键字,但我并没有想出来。
以下是代码:
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;
}
任何建议都会受到很大关注!
谢谢, Omri
答案 0 :(得分:0)
yield
在这里不会帮到你。 RunWorkerCompleted
在UI线程上执行。显然实例化ObservableCollection<int>
需要很长时间。最简单的解决方案可能是将实例化移动到后台线程(DoWork
)。它也可能是一个PropertyChanged
事件处理程序需要很长时间,在这种情况下它也应该在后台线程上运行。
答案 1 :(得分:0)
这里有一些事情。 1)当您的包含它的对象被实例化时,应该创建您的worker及其委托。
public class ViewModel
{
BackgroundWorker _primeWorker;
public ViewModel()
{
_primeWorker = new BackgroundWorker;
_primeWorker.DoWork += ...
}
public void AddSomeNumbers()
{
if(_primerWorker.IsBusy == false)
_primeWorker.RunWorkerAsync();
}
}
2)当实例化包含它的对象时,应该实例化您的集合,以避免在使用此类的对象调用get
时抛出null异常。
3)添加许多项会导致因每次添加数字而导致缓慢,因此会触发UI线程必须处理的事件。
此链接有更多信息可以帮助您。 http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx