2

I'm working on a universal app to run on Windows 8.1 & Windows Phone 8.1. In the older Silverlight based Windows Phone apps, I could have a handy helper on my View Model something like:

protected delegate void OnUIThreadDelegate();
protected static void OnUIThread(OnUIThreadDelegate onUIThreadDelegate)
{
    if (onUIThreadDelegate != null)
    {
        if (Deployment.Current.Dispatcher.CheckAccess())
        {
            onUIThreadDelegate();
        }
        else
        {
            Deployment.Current.Dispatcher.BeginInvoke(onUIThreadDelegate);
        }
    }
}

From what I've seen of using async I should be able to do something like:

async void Watcher_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
    this.Latitude = args.Position.Coordinate.Point.Position.Latitude;
    this.Longitude = args.Position.Coordinate.Point.Position.Longitude;

    // TODO: Consider reloading;
    var ev = await SpecialEvent.SearchNearAsync();
    this.Events.Clear(); // this is an ObservableCollection that the XAML is bound to,
                         // and I'm seeing it blow up with RPC_E_WRONG_THREAD here
}

Other options utilising the Dispatcher seem to be harder, as, in universal apps, Application.Current does not have a Dispatcher property?

So what are the options left? do I have to change my View-Models to allow the dispatcher to be passed from the View, or am I missing something more obvious?

Community
  • 1
  • 1
Rowland Shaw
  • 37,700
  • 14
  • 97
  • 166
  • On the linked answer the event handler is running on the UI thread, that's why they can use `async-await`. Is your case the same? does the Watcher_PositionChanged runs on the UI thread? – i3arnon Jun 07 '14 at 18:23

1 Answers1

4

You can get the dispatcher from any thread using:

var dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher;

About the async - what it does is invoke (part of) the awaited method in another thread and when it finishes, return to the first thread and continue execution there. So in your case, the Watcher_PositionChanged method is just not invoked in the UI thread and so it has no access to UI elements.

Note (about async in general): If you have an async method, it is not automatically invoked in another thread. If you want to execute part of it in a different thread, you have to manually tell it to do so. Otherwise it's pretty mush sync. Also, when awaiting you can configure it to continue on the second thread - the one created for the async work.

yasen
  • 3,580
  • 13
  • 25