UWP 等待 HttpClient 不工作
UWP await on HttpClient not working
我正在尝试从网络 API 获得 JSON 响应。
我可以使用类似的代码在控制台应用程序中检索响应,但是在 UWP 中 await httpClient.GetAsync(uri);
无法按预期工作。
public static async Task<double> GetJson()
{
using (var httpClient = new HttpClient())
{
Uri uri= new Uri("https://api.cryptonator.com/api/ticker/btc-usd");
HttpResponseMessage response = await httpClient.GetAsync(uri);
//Below code is not relevent since code is failing on await
var result = response.Content.ReadAsStringAsync();
var jsonResponse = Json.ToObjectAsync<ExchangeRate>(result);//
jsonResponse.Wait();//
ExchangeRate exchangeRateObj = jsonResponse.Result;//
return 1.2;//
}
}
后面的代码:
private void Button_Click(object sender,RoutedEventArgs e){
var ROC__ = MyClass.GetJson();
ROC__.Wait();
currency_.ROC = ROC__.Result;
}
这里不起作用是什么意思?
它应该连接到 URL 并获取响应并且应该为响应分配一些值。相反,在使用 step into 或 Continue 进行调试时,控件退出当前行也会跳过后续行。
(我也在下一行进行了调试),应用程序冻结了。
我在 Whosebug 和其他博客上参考了 JSON 与 HTTPClient
解析的类似代码,建议使用 System.Net.Http
或 Windows.Web.Http
相关问题: how-to-get-a-json-string-from-url
我认为任务是 运行 并且它一直在等待模式,这看起来很奇怪,因为调试模式不显示代码是 运行,它只显示 ready
。也不例外。
我是不是做错了什么或遗漏了一些 Nuget 参考资料?
求推荐。
PS : httpClient.GetStringAsync
方法也一样。
在控制台应用程序上,此行有效但不适用于 UWP
var json = new WebClient().DownloadString("https://api.cryptonator.com/api/ticker/btc-usd");
与
不重复
- 它不是 Xamarin,尽管它是基于 C# 的,但我的代码不同,它不是我关心的 WebApiClient 或 GetInformationAsync 方法。
指定的代码有几个错误需要修复。首先,标记您的事件处理程序 async
:
private async void Button_Click(object sender, RoutedEventArgs e)
其次,await GetJson
因为这是一个异步方法,所以最好在它的名称后加上后缀"Async";因此,等待 GetJsonAsync
:
currency_.ROC = await MyClass.GetJsonAsync();
现在,回到 GetJsonAsync
本身,ReadAsStringAsync
和 ToObjectAsync
也应该等待:
private static async Task<double> GetJsonAsync()
{
using (var httpClient = new HttpClient())
{
Uri uri = new Uri("https://api.cryptonator.com/api/ticker/btc-usd");
HttpResponseMessage response = await httpClient.GetAsync(uri);
string result = await response.Content.ReadAsStringAsync();
//Below code is not relevent since code is failing on await
ExchangeRate exchangeRateObj = await Json.ToObjectAsync<ExchangeRate>(result);
return 1.2;//
}
}
之前不工作的原因是await
调用和.Wait()
的同步块之间的上下文切换造成了死锁。查找有关 here.
的更多信息
您的代码运行良好。我在下面重新生成了它。摆脱你正在做的那个不稳定的等待电话。
这样做。创建一个新的 uwp 应用程序,粘贴下面的代码并在 return 上放置一个断点并查看它是否被执行。
无论您是否使按钮处理程序异步,它都会起作用。如果您不将其设为 asnyc,那么请求将不会异步执行
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
SomeClass.GetJson();
}
}
public class SomeClass
{
public static async Task<double> GetJson()
{
using (var httpClient = new HttpClient())
{
Uri uri = new Uri("https://api.cryptonator.com/api/ticker/btc-usd");
HttpResponseMessage response = await httpClient.GetAsync(uri);
return 1.2;
}
}
}
我可以借此机会无耻地插入我的 UWP 库。它为您完成这项工作。
https://github.com/DotNetRussell/UWPLibrary
在 BasecodeRequestManager.cs 文件中有一个 BeginRequest 函数可以为您异步完成这项工作。该库还有许多其他功能。
所以我自己试了一下。不幸的是你的信息有点不完整 header:
对于 Json-Handling 我使用了 Newtonsoft,因为我在我的 UWP 环境中没有找到 Json.ToObjectAsync
。
为了创建 ExchangeRate
- class,我使用了 Json2CSharp。
这里是汇率 classes:
public class ExchangeRate
{
public string Error { get; set; }
public bool Success { get; set; }
public Ticker Ticker { get; set; }
public int Timestamp { get; set; }
}
public class Ticker
{
public string @Base { get; set; }
public string Change { get; set; }
public string Price { get; set; }
public string Target { get; set; }
public string Volume { get; set; }
}
我将 Button_Click
-Method 更改为 async void
。通常不建议使用 async void
而不是 async Task
。但是因为它是来自 UI-Element 的处理程序,所以这不是问题,因为无论如何源都不会等待,您不应该直接从 code-behind 调用此方法。
Button_Click
-方法:
private async void Button_Click(object sender, RoutedEventArgs e)
{
var ROC__ = await MyClass.GetJson();
//Do whatever you want with the result.
//Its a double, maybe you want to return an ExchangeRate objcet insted
}
在您的 GetJson
-Method 中,您需要为异步操作添加 await,或者直接在方法之后添加 .Wait()
而不是在新行中。您需要这样做,因为当您调用异步操作并且 .Wait()
迟到时,任务会自动开始 运行。所以你的 GetJson-Method 看起来像这样:
public static async Task<Double> GetJson()
{
using (var httpClient = new HttpClient())
{
Uri uri = new Uri("https://api.cryptonator.com/api/ticker/btc-usd");
HttpResponseMessage response = await httpClient.GetAsync(uri);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var result = await response.Content.ReadAsStringAsync();
ExchangeRate rate = JsonConvert.DeserializeObject<ExchangeRate>(result); //Newtonsoft
return 1.2;
}
else
{
return -1; //Example value
}
}
}
此外,我添加了一个检查,如果请求成功,可以肯定的是,我们有一个响应。我之前是怎么说的:我认为你应该 return a ExchangeRat
e-object 而不是 double,但这取决于你的上下文。
我正在尝试从网络 API 获得 JSON 响应。
我可以使用类似的代码在控制台应用程序中检索响应,但是在 UWP 中 await httpClient.GetAsync(uri);
无法按预期工作。
public static async Task<double> GetJson()
{
using (var httpClient = new HttpClient())
{
Uri uri= new Uri("https://api.cryptonator.com/api/ticker/btc-usd");
HttpResponseMessage response = await httpClient.GetAsync(uri);
//Below code is not relevent since code is failing on await
var result = response.Content.ReadAsStringAsync();
var jsonResponse = Json.ToObjectAsync<ExchangeRate>(result);//
jsonResponse.Wait();//
ExchangeRate exchangeRateObj = jsonResponse.Result;//
return 1.2;//
}
}
后面的代码:
private void Button_Click(object sender,RoutedEventArgs e){
var ROC__ = MyClass.GetJson();
ROC__.Wait();
currency_.ROC = ROC__.Result;
}
这里不起作用是什么意思?
它应该连接到 URL 并获取响应并且应该为响应分配一些值。相反,在使用 step into 或 Continue 进行调试时,控件退出当前行也会跳过后续行。 (我也在下一行进行了调试),应用程序冻结了。
我在 Whosebug 和其他博客上参考了 JSON 与 HTTPClient
解析的类似代码,建议使用 System.Net.Http
或 Windows.Web.Http
相关问题: how-to-get-a-json-string-from-url
我认为任务是 运行 并且它一直在等待模式,这看起来很奇怪,因为调试模式不显示代码是 运行,它只显示 ready
。也不例外。
我是不是做错了什么或遗漏了一些 Nuget 参考资料?
求推荐。
PS : httpClient.GetStringAsync
方法也一样。
在控制台应用程序上,此行有效但不适用于 UWP
var json = new WebClient().DownloadString("https://api.cryptonator.com/api/ticker/btc-usd");
与
- 它不是 Xamarin,尽管它是基于 C# 的,但我的代码不同,它不是我关心的 WebApiClient 或 GetInformationAsync 方法。
指定的代码有几个错误需要修复。首先,标记您的事件处理程序 async
:
private async void Button_Click(object sender, RoutedEventArgs e)
其次,await GetJson
因为这是一个异步方法,所以最好在它的名称后加上后缀"Async";因此,等待 GetJsonAsync
:
currency_.ROC = await MyClass.GetJsonAsync();
现在,回到 GetJsonAsync
本身,ReadAsStringAsync
和 ToObjectAsync
也应该等待:
private static async Task<double> GetJsonAsync()
{
using (var httpClient = new HttpClient())
{
Uri uri = new Uri("https://api.cryptonator.com/api/ticker/btc-usd");
HttpResponseMessage response = await httpClient.GetAsync(uri);
string result = await response.Content.ReadAsStringAsync();
//Below code is not relevent since code is failing on await
ExchangeRate exchangeRateObj = await Json.ToObjectAsync<ExchangeRate>(result);
return 1.2;//
}
}
之前不工作的原因是await
调用和.Wait()
的同步块之间的上下文切换造成了死锁。查找有关 here.
您的代码运行良好。我在下面重新生成了它。摆脱你正在做的那个不稳定的等待电话。
这样做。创建一个新的 uwp 应用程序,粘贴下面的代码并在 return 上放置一个断点并查看它是否被执行。
无论您是否使按钮处理程序异步,它都会起作用。如果您不将其设为 asnyc,那么请求将不会异步执行
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
SomeClass.GetJson();
}
}
public class SomeClass
{
public static async Task<double> GetJson()
{
using (var httpClient = new HttpClient())
{
Uri uri = new Uri("https://api.cryptonator.com/api/ticker/btc-usd");
HttpResponseMessage response = await httpClient.GetAsync(uri);
return 1.2;
}
}
}
我可以借此机会无耻地插入我的 UWP 库。它为您完成这项工作。
https://github.com/DotNetRussell/UWPLibrary
在 BasecodeRequestManager.cs 文件中有一个 BeginRequest 函数可以为您异步完成这项工作。该库还有许多其他功能。
所以我自己试了一下。不幸的是你的信息有点不完整 header:
对于 Json-Handling 我使用了 Newtonsoft,因为我在我的 UWP 环境中没有找到 Json.ToObjectAsync
。
为了创建 ExchangeRate
- class,我使用了 Json2CSharp。
这里是汇率 classes:
public class ExchangeRate
{
public string Error { get; set; }
public bool Success { get; set; }
public Ticker Ticker { get; set; }
public int Timestamp { get; set; }
}
public class Ticker
{
public string @Base { get; set; }
public string Change { get; set; }
public string Price { get; set; }
public string Target { get; set; }
public string Volume { get; set; }
}
我将 Button_Click
-Method 更改为 async void
。通常不建议使用 async void
而不是 async Task
。但是因为它是来自 UI-Element 的处理程序,所以这不是问题,因为无论如何源都不会等待,您不应该直接从 code-behind 调用此方法。
Button_Click
-方法:
private async void Button_Click(object sender, RoutedEventArgs e)
{
var ROC__ = await MyClass.GetJson();
//Do whatever you want with the result.
//Its a double, maybe you want to return an ExchangeRate objcet insted
}
在您的 GetJson
-Method 中,您需要为异步操作添加 await,或者直接在方法之后添加 .Wait()
而不是在新行中。您需要这样做,因为当您调用异步操作并且 .Wait()
迟到时,任务会自动开始 运行。所以你的 GetJson-Method 看起来像这样:
public static async Task<Double> GetJson()
{
using (var httpClient = new HttpClient())
{
Uri uri = new Uri("https://api.cryptonator.com/api/ticker/btc-usd");
HttpResponseMessage response = await httpClient.GetAsync(uri);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var result = await response.Content.ReadAsStringAsync();
ExchangeRate rate = JsonConvert.DeserializeObject<ExchangeRate>(result); //Newtonsoft
return 1.2;
}
else
{
return -1; //Example value
}
}
}
此外,我添加了一个检查,如果请求成功,可以肯定的是,我们有一个响应。我之前是怎么说的:我认为你应该 return a ExchangeRat
e-object 而不是 double,但这取决于你的上下文。