Reputation: 23157
I'm writing a WPF app using an MVVM approach. In my ViewModel, I have an ObservableCollection. Periodically, my app needs to check for new messages, and, if there are any, it needs to add them to the ObservableCollection.
If I try to add to the ObservableCollection in the DoWork, it doesn't work because of thread synchronization issues. It looks like the easiest way to get this to happen on the UI thread is to do a ReportProgress() and update the collection from there.
My question is: Philosophically and technically, is it ok to update the UI from the ReportProgress handler, even though "by the letter of the law" I'm not actually reporting progress.
Is there a more sound way to do this?
* EDIT: Code works using Dispatcher Timer *
ViewModel
class MyViewModel
{
public ObservableCollection<string> MyList { get; set; }
public MyViewModel()
{
MyList = new ObservableCollection<string>();
}
}
"teh codez" - just a sample, not my actual application code.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
MyViewModel mvm = new MyViewModel();
this.DataContext = mvm;
DispatcherTimer mytimer = new DispatcherTimer();
mytimer.Interval = TimeSpan.FromSeconds(5.0);
mytimer.Tick += new EventHandler(mytimer_Tick);
mytimer.Start();
}
void mytimer_Tick(object sender, EventArgs e)
{
((DispatcherTimer)sender).Stop();
MyViewModel mvm = this.DataContext as MyViewModel;
mvm.MyList.Insert(0, DateTime.Now.ToLongTimeString());
((DispatcherTimer)sender).Start();
}
This looks like it will work well for what I need, and doesn't give me additional baggage that I'm not going to use (e.g. cancel, workercompleted, etc.).
Upvotes: 0
Views: 399
Reputation: 2007
If you're implementing polling-type functionality in your app, it probably makes more sense to use a DispatcherTimer that fires at an interval instead of constantly looping inside of the BackgroundWorker.
http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer.aspx
Upvotes: 1
Reputation: 29584
I wouldn't do it
It "feels" like something that will cause problems in the future (maybe when someone else tries to add features years from now, maybe when this code is upgraded or ported to an environment with slightly different ReportProgress implementation).
I would just use Dispatcher.BeginInvoke (I also try to avoid using Invoke because it makes one thread wait for the other and reduce the efficiency of using multi-threading in the first place).
But, there are places where just using ReportProgress is the right choice, you need to decide for yourself what is the best thing for your specific situation (the thing I hate most is valuing "best practices" or "architecture" more then producing actual working software)
Upvotes: 1
Reputation: 10813
Sure. That's what the UserState of the EventArgs is designed for.
The reason for the BackgroundWorker is to simplify multithreading. Otherwise, you'd have to do something like Invoke (or BeginInvoke) to handle the same thing the BackgroundWorker is being used for.
Upvotes: 1