分离异步 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
不是异步的,接口方法也不是。两个选项:
- 制作接口方法return
Task
.
- 将同步下载放在线程池上:
await Task.Run(() => _downloadClient.GetDataAsync(uri));
。这是一个快速修复。如果同时下载很少运行,那么这不是性能或内存问题,而是有效的修复。
我正在尝试从休息服务下载 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
不是异步的,接口方法也不是。两个选项:
- 制作接口方法return
Task
. - 将同步下载放在线程池上:
await Task.Run(() => _downloadClient.GetDataAsync(uri));
。这是一个快速修复。如果同时下载很少运行,那么这不是性能或内存问题,而是有效的修复。