分离异步 HttpClient 和 Ui 线程 Winrt?

separating asynchronous HttpClient and Ui thread Winrt?

我正在尝试从休息服务下载 json 数据以及我正在做的一切 用于单击按钮导航到新页面,在新页面中我是 使用异步方法下载数据。

但是 UI 仍然卡住... ui 卡在第一页直到下载完成.. 我试过在 PageLoaded 事件上使用异步 .. 并在页面其他元素上的许多其他加载事件..我如何将它们分开?

 private async void Page_Loaded(object sender, RoutedEventArgs e)
    {
        //download helper
        IWebService _downloadClient = new DownloadClient();
        var _JsonString = _downloadClient.GetDataAsync(uri);
        //Json to Object Converter
        IJsonDeserializer _deserializer = new JsonToObject();
        ApodProp = _deserializer.DesrializeTo<RootObject>(_JsonString);


        apobinding(); //sets some textblocks to the data downloaded
    }

整个页面直到下载完成才出现,我没有使用任何 await,因为下载客户端的内部方法使用 async 和 await 关键字..

下载客户端已编辑:

public Task<string> GetDataAsync(string uri)
        {
            //throw new NotImplementedException();
            try
            {
                using (HttpClient Client = new HttpClient())
                {
                    Task<HttpResponseMessage> _result = Client.GetAsync(uri);
                    HttpResponseMessage responseData = _result.Result;
                    return await responseData.Content.ReadAsStringAsync();
                }
            }
            catch (HttpRequestException)
            {

                MessageDialog md = new MessageDialog("Http exception");
               await md.ShowAsync();
            }

            return null;
        }

更新: 即使是现在,我的 UI 也不会在下载完成之前出现。

 protected override async void OnNavigatedTo(NavigationEventArgs e)
    {
        HardwareButtons.BackPressed += HardwareButtons_BackPressed;
        await MyTask();    
    }

我的任务:

private async Task MyTask()
        {
            IApiService _apiProvider = new RestClient.ApiService.NasaAPOD();
            var formattableString = _apiProvider.GetFormattableApiCallString("api_key;concept_tags");

            IParameterFiller filler = new ParameterFiller();
            var uri = filler.FillParameters(formattableString, "I3pA7RdSKvrER6hm6f51BhWzCmoJM6Alq6BjbbEu;true");

            IWebService _downloadClient = new DownloadClient();
            var _JsonString = await _downloadClient.GetDataAsync(uri);

            IJsonDeserializer _deserializer = new JsonToObject();
            ApodProp = _deserializer.DesrializeTo<RootObject>(_JsonString);


            apobinding();
        }

终于成功了

await Task.Run(()=> { MyTask();  }  ); 
        apobinding();

这就是你需要的一切......

现在进入概念部分... 在 windows 中有一条规则,必须从线程访问控件 它们是从中创建的,任何包含 ui 控件的代码都必须 运行 在同一线程上,除非您明确指定它 ...

在第一种情况下,ui 线程即 apobinding 与下载代码一起使用,因此整个 UI 线程被冻结。

为了获得响应,我不得不将下载放到一个单独的过程中。

然后我尝试将 ui 放入 MyTask 和 task.run .. 这两种方式都导致了类似的 o/p .. 是的,正如您根据线程的 windows 规则如果 ui 控制从创建它的任何其他线程访问将导致 Crash Crash Crash

我在响应速度方面经历了一段非常艰难的时期......但不要忘记,如果您的应用程序没有响应,用户将卸载它,无论是 VS 还是 Windows 或 Mac 或 Linux 或任何其他伟大的软件.. 所以让 UI 响应并成为最好的(讽刺.. 还有很多事情要做)。

在评论中,您说 _downloadClient.GetDataAsync 不是异步的,接口方法也不是。两个选项:

  1. 制作接口方法return Task.
  2. 将同步下载放在线程池上:await Task.Run(() => _downloadClient.GetDataAsync(uri));。这是一个快速修复。如果同时下载很少运行,那么这不是性能或内存问题,而是有效的修复。