I designed a WPF application based on MVVM pattern and I need to get large amount of data from a webservice, and i do it with a BackgroundWorker inside the ViewModel. To modify the observable collection i have to use a dispatcher and the problem is here, even if i pass by reference UI Dispa开发者_如何转开发tcher it dosen't work, it is like I use the inner dispatcher and my application get freezed until all data are retrived.
I try to get the UI Dispatcher in several ways, Dispatcher.CurrentDispatcher, Application.Dispatcher, App.Current.Dispatcher... doing some researches I read that it should be works, does someone have any suggestions?
Thank you Marco
Update
Here some code: This is how I pass the Dispatcher to the ModelView
void AppWindow_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = new ModelViewApplication(System.Windows.Threading.Dispatcher.CurrentDispatcher);
}
Then I try to get data in this way
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
....
}));
}
It seems like the multithread dosen't work
Use the BackgroundWorker
to get your data, then use the RunWorkerCompleted
to update the ObservableCollection
. You shouldn't need the Dispatcher
at all
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);
}
Here is a sample which may help you implementing the task and UI Updates. You can easily convert the following sample to you scenario. You can have a look at my blog which has detailed Explanation regarding this error and solution
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
});
});
精彩评论