我设计了一个基于MVVM模式的WPF应用程序,我需要从Web服务中获取大量数据,我使用ViewModel中的BackgroundWorker来完成。要修改可观察集合,我必须使用调度程序,问题在这里,即使我通过引用UI Dispatcher传递它也不起作用,就像我使用内部调度程序,我的应用程序被冻结,直到所有数据都被重新检索。
我尝试以多种方式获取UI Dispatcher,Dispatcher.CurrentDispatcher,Application.Dispatcher,App.Current.Dispatcher ......做一些研究我读到它应该有效,有人有什么建议吗?
谢谢 马可
更新
这里有一些代码:这就是我将Dispatcher传递给ModelView的方法
void AppWindow_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = new ModelViewApplication(System.Windows.Threading.Dispatcher.CurrentDispatcher);
}
然后我尝试以这种方式获取数据
public ModelViewApplication(Dispatcher _dispatcher)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(getData);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(completedData);
bw.RunWorkerAsync();
}
public void getData(object sender, DoWorkEventArgs e)
{
_dispatcher.Invoke(DispatcherPriority.Normal,
new Action(
delegate()
{
//Connect to webservice and retrieve data
....
}));
}
似乎多线程不起作用
答案 0 :(得分:3)
使用BackgroundWorker
获取您的数据,然后使用RunWorkerCompleted
更新ObservableCollection
。您根本不需要Dispatcher
public ModelViewApplication()
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(getData);
bw.RunWorkerCompleted += completedData;
bw.RunWorkerAsync();
}
public void getData(object sender, DoWorkEventArgs e)
{
//Connect to webservice and retrieve data
e.Result = WebService.GetData();
}
private void completedData(object sender, RunWorkerCompletedEventArgs e)
{
MyCollection = new ObservableCollection<SomeClass>((IList)e.Results);
}
答案 1 :(得分:0)
以下示例可帮助您实现任务和UI更新。您可以轻松地将以下示例转换为您的方案。 您可以查看我的博客,其中包含有关此错误和解决方案的详细说明
http://bathinenivenkatesh.blogspot.com/2011/07/wpf-build-more-responsive-ui.html
ObservableCollection images = new ObservableCollection();
TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
for (int i = 0; i < 50; i++)
{
//GET IMAGE Path FROM SERVER
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
// UPDATE PROGRESS BAR IN UI
});
images.Add(("");
}
}).ContinueWith(t =>
{
if (t.IsFaulted)
{
// EXCEPTION IF THREAD IS FAULT
throw t.Exception;
}
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
//PROCESS IMAGES AND DISPLAY
});
});