7
votes

I am using MVVMCross with my cross-platform Windows Phone and Android app. In the core project's main view model, I am doing some background work using TPL and I want to make sure that in the callback, when I make changes to the properties of the view model which will trigger UI change, that the code is run on UI thread, how do I achieve this?

For code, here is how it likes

    private MvxGeoLocation _currentLocation;
    private Task<MvxGeoLocation> GetCurrentLocation()
    {
        return Task.Factory.StartNew(() =>
            {
                while (_currentLocation == null && !LocationRetrievalFailed)
                {
                }
                return _currentLocation;
            });
    }

    var location = await GetCurrentLocation();
    if (LocationRetrievalFailed)
    {
        if (location == null)
        {
            ReverseGeocodingRequestFailed = true;
            return;
        }
        // Show toast saying that we are using the last known location
    }
    Address = await GooglePlaceApiClient.ReverseGeocoding(location);
3

3 Answers

16
votes

Did you try IMvxMainThreadDispatcher?

var dispatcher = Mvx.Resolve<IMvxMainThreadDispatcher>();
dispatcher.RequestMainThreadAction(()=> { .... });

See more on the implementation:

https://github.com/MvvmCross/MvvmCross/search?q=IMvxMainThreadDispatcher&type=Code

Usually I don't think you need this though.

Since you start the async processing from main thread, the async operations should return back to main thread.

Can you give an example of the async code you are doing?

3
votes

Method RequestMainThreadAction is now obsolete. Today you have to do

var dispatcher = Mvx.Resolve<IMvxMainThreadAsyncDispatcher>();
await dispatcher.ExecuteOnMainThreadAsync(()=> { .... });
3
votes

Update on 24th August 2020: As @claudio-redi has mentioned, ExecuteOnMainThreadAsync needs to be used. But Mvx.Resolve is now obsolete. So the latest snippet would be:

var mainThreadAsyncDispatcher = Mvx.IoCProvider.Resolve<IMvxMainThreadAsyncDispatcher>();
await mainThreadAsyncDispatcher.ExecuteOnMainThreadAsync( async ()=> { await SomeAsyncTask() });