无法使用UI线程Dispatcher更新UI?

时间:2011-08-18 12:25:36

标签: wpf mvvm backgroundworker dispatcher

我设计了一个基于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
                 ....
                 }));
}

似乎多线程不起作用

2 个答案:

答案 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 
    }); 
});