MVVM: Using a Timer in your ViewModel
Yesterday I found myself needing to periodically sample data for a real-time chart and realized that the “Timer” classes in System.Threading and System.Windows didn’t quite work as expected, raising the following exception:
The calling thread must be STA, because many UI components require this.
We get this error because when we use the other Timer classes they create a separate thread in the background on which the “Tick”/”Elapsed” events are raised; this is an issue when updating “notify-able” properties which are bound to elements in the UI because the UI must be edited from the thread it was created on (not thread-safe). This proves itself to be rather inconvenient when using a pattern like MVVM, where we don’t have a handle to an element from the UI in our ViewModel to synchronize with. After a bit of googling and playing around, I discovered the DispatcherTimer class in System.Windows.Threading. As it works out, this timer’s “Tick” event is always raised on the main UI thread.
Here’s a brief example of one way to implement the DispatcherTimer:
// This code creates a new DispatcherTimer with an interval of 15 seconds. DispatcherTimer timer = new DispatcherTimer(); ... timer = new DispatcherTimer(); timer .Interval = new TimeSpan(0, 0, 15); timer .Tick += new EventHandler(this.InvalidateSampleData); // Start the timer. Note that this call can be made from any thread. timer.Start(); ... private void InvalidateSampleData(object state, EventArgs e) { // Timer callback code here... }
Over and out!