更新View模型时如何避免RPC_E_WRONG_THREAD?

时间:2014-06-07 16:24:41

标签: c# async-await windows-phone-8.1 win-universal-app

我正在开发一个可在Windows 8.1和Windows上运行的通用应用。 Windows Phone 8.1。在较旧的基于Silverlight的Windows Phone应用程序中,我可以在我的View Model上找到一个方便的帮助器:

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);
        }
    }
}

从我所看到的使用asyncshould be able做以下事情:

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
}

使用Dispatcher的其他选项似乎更难,因为在通用应用中,Application.Current没有Dispatcher属性?

那剩下的选择是什么?我是否必须更改我的View-Models以允许从View传递调度程序,或者我错过了一些更明显的东西?

1 个答案:

答案 0 :(得分:4)

您可以使用

从任何主题获取调度程序
var dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher;

关于异步 - 它的作用是在另一个线程中调用(等待)等待的方法,当它完成时,返回第一个线程并继续执行。因此,在您的情况下,Watcher_PositionChanged方法不会在UI线程中调用,因此它无法访问UI元素。

注意(关于一般的异步):如果您有异步方法,则不会在另一个线程中自动调用它。如果要在不同的线程中执行其中的一部分,则必须手动告诉它这样做。否则它很容易同步。此外,在等待时,您可以将其配置为在第二个线程上继续 - 为异步工作创建的线程。