Не удается обновить интерфейс с помощью диспетчера потоков UI? - PullRequest
1 голос
/ 18 августа 2011

Я разработал приложение WPF на основе шаблона MVVM, и мне нужно получить большой объем данных из веб-службы, и я делаю это с помощью BackgroundWorker внутри ViewModel.Чтобы изменить наблюдаемую коллекцию, мне нужно использовать диспетчер, и проблема здесь, даже если я передаю справочный UI Dispatcher, он не работает, все равно, что я использую внутренний диспетчер, и мое приложение замораживается до тех пор, пока все данные не будут получены.

Я пытаюсь получить Диспетчер пользовательского интерфейса несколькими способами: Dispatcher.CurrentDispatcher, Application.Dispatcher, App.Current.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 ]

3 голосов
/ 18 августа 2011

Используйте 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);
}
0 голосов
/ 18 августа 2011

Вот пример, который может помочь вам в реализации задачи и обновлений пользовательского интерфейса. Вы можете легко преобразовать следующий пример в ваш сценарий. Вы можете взглянуть на мой блог, в котором есть подробное объяснение относительно этой ошибки и решения

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 
    }); 
});
...