WPF/Multithreading: UI Dispatcher in MVVM
I tend to have my ViewModels inherit from DependencyObject and ensure that they are constructed on the UI thread, which poises them perfectly to handle this situation - they have a Dispatcher
property that corresponds to the UI thread's dispatcher. Then, you don't need to pollute your view with the ViewModel's implementation details.
Some other pluses:
- Unit testability: you can unit test these without a running application (rather than relying on
Application.Current.Dispatcher
) - Loose coupling between View & ViewModel
- You can define dependency properties on your ViewModel and write no code to update the view as those properties change.
I usually use Application.Current.Dispatcher
: since Application.Current
is static, you don't need a reference to a control
From Caliburn Micro source code :
public static class Execute
{
private static Action<System.Action> executor = action => action();
/// <summary>
/// Initializes the framework using the current dispatcher.
/// </summary>
public static void InitializeWithDispatcher()
{
#if SILVERLIGHT
var dispatcher = Deployment.Current.Dispatcher;
#else
var dispatcher = Dispatcher.CurrentDispatcher;
#endif
executor = action =>{
if(dispatcher.CheckAccess())
action();
else dispatcher.BeginInvoke(action);
};
}
/// <summary>
/// Executes the action on the UI thread.
/// </summary>
/// <param name="action">The action to execute.</param>
public static void OnUIThread(this System.Action action)
{
executor(action);
}
}
Before using it you'll have to call Execute.InitializeWithDispatcher()
from the UI thread then you can use it like this Execute.OnUIThread(()=>SomeMethod())