【问题标题】:UI Thread issue with view model in MVVMCrossMVVMCross 中视图模型的 UI 线程问题
【发布时间】:2020-08-24 13:47:56
【问题描述】:

我将 MVVMCross 与我的跨平台 Windows Phone 和 Android 应用程序一起使用。在核心项目的主视图模型中,我正在使用 TPL 做一些后台工作,我想确保在回调中,当我对将触发 UI 更改的视图模型的属性进行更改时,代码运行在UI线程,我该如何实现?

对于代码,这是它喜欢的方式

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

【问题讨论】:

    标签: mvvm mvvmcross


    【解决方案1】:

    你试过IMvxMainThreadDispatcher吗?

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

    查看更多关于实现的信息:

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

    通常我认为你不需要这个。

    由于您从主线程开始异步处理,因此异步操作应该返回到主线程。

    你能举一个你正在做的异步代码的例子吗?

    【讨论】:

    • 在这里也可以看到很多问题——比如stackoverflow.com/questions/16142629/…
    • 我添加了一些代码示例。另外我想知道在主 UI 线程以外的线程中修改 ViewModel 属性是否安全?
    • 当你说“既然你从主线程开始异步处理,异步操作应该返回到主线程。”,你是说 C# 5.0 的 async/await 还是只是 Task?或两者?我想知道我是否将 ContinueWith 回调附加到 Task,它是在调用者的线程上还是在 Task 的线程上?
    • 别管我之前的问题,我自己写个测试试试看
    • ContinueWith 返回调用者线程。再次调用 await 是一样的。这是一个很好的阅读:jaylee.org/post/2012/06/18/…
    【解决方案2】:

    2020 年 8 月 24 日更新: 正如@claudio-redi 所提到的,需要使用ExecuteOnMainThreadAsync。但是Mvx.Resolve 现在已经过时了。所以最新的 sn-p 将是:

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

    【讨论】:

      【解决方案3】:

      方法RequestMainThreadAction 现已过时。今天你要做的事

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多