On all MvvmCross platforms, it is required that user interfaces reconnect to the interface thread / apartment, but each platform does it differently ....
To get around this, MvvmCross provides a cross-platform way to do this - using the IMvxViewDispatcherProvider object.
For example, in WindowsPhone, IMvxViewDispatcherProvider provides the ultimate MvxMainThreadDispatcher at https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxMainThreadDispatcher.
This implements InvokeOnMainThread using:
private bool InvokeOrBeginInvoke(Action action) { if (_uiDispatcher.CheckAccess()) action(); else _uiDispatcher.BeginInvoke(action); return true; }
For code in ViewModels:
- your
ViewModel inherits from MvxViewModel MvxViewModel inherits from MvxApplicationObjectMvxApplicationObject inherits from MvxNotifyPropertyChanged- the
MvxNotifyPropertyChanged object inherits from MvxMainThreadDispatchingObject
MvxMainThreadDispatchingObject https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/ViewModels/MvxMainThreadDispatchingObject.cs
public abstract class MvxMainThreadDispatchingObject : IMvxServiceConsumer<IMvxViewDispatcherProvider> { protected IMvxViewDispatcher ViewDispatcher { get { return this.GetService().Dispatcher; } } protected void InvokeOnMainThread(Action action) { if (ViewDispatcher != null) ViewDispatcher.RequestMainThreadAction(action); } }
So ... your ViewModel can just call InvokeOnMainThread(() => DoStuff());
Another point that should be noted is that MvvmCross automatically performs user interface thread conversions for property updates that are passed to the MvxViewModel (or even any MvxNotifyPropertyChanged object) using the RaisePropertyChanged() methods - see:
protected void RaisePropertyChanged(string whichProperty) { // check for subscription before going multithreaded if (PropertyChanged == null) return; InvokeOnMainThread( () => { var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(whichProperty)); }); }
at https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNotifyPropertyChanged.cs
This automatic sorting of RaisePropertyChanged() calls works well in most situations, but it can be a little inefficient if you raise a lot of changed properties from a background thread - this can lead to a lot of context switching of the stream. This is not something you need to know about in most of your codes, but if you ever find it to be a problem, it can help change the code, for example:
MyProperty1 = newValue1; MyProperty2 = newValue2;
in
InvokeOnMainThread(() => { MyProperty1 = newValue1; MyProperty2 = newValue2; // ... MyProperty10 = newValue10; });
If you have ever used an ObservableCollection , then note that MvvmCross does not sort the threads for the INotifyPropertyChanged or INotifyCollectionChanged events fired by these classes, so for you as a developer to change these changes.
Reason: ObservableCollection exists in the MS and Mono base codes, so there is no easy way that MvvmCross can modify these existing implementations.