我正在尝试从web API获取JSON响应。
我可以用类似的代码在控制台应用程序中检索响应,但在UWPawait 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进行调试时,控件退出,当前行也会跳过后续行。(我也在接下来的几行中进行了调试(,应用程序刚刚冻结。
我在Stackoverflow和其他博客上引用了类似的HTTPClient
解析JSON的代码,建议使用System.Net.Http
或Windows.Web.Http
相关问题:如何生成t-a-json-string-from-url
我认为任务正在运行,它将永远处于等待模式,这似乎很奇怪,因为调试模式不显示正在运行的代码,它只显示ready
。也不例外。
我是做错了什么还是遗漏了一些Nuget参考资料?
请提出建议。
PS:httpClient.GetStringAsync
方法也是如此。在控制台应用程序上,这条线有效,但在UWP 上无效
var json = new WebClient().DownloadString("https://api.cryptonator.com/api/ticker/btc-usd");
不重复的httpclient getasync永远不会在xamarin android 上返回
- 它不是Xamarin,尽管它是基于C#的,但我的代码不同,它不是我关心的WebApiClient或GetInformationAsync方法
指定的代码中有几个错误需要纠正。首先,标记您的事件处理程序async
:
private async void Button_Click(object sender, RoutedEventArgs e)
其次,等待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()
的同步块之间的上下文切换导致了死锁。点击此处了解更多信息。
您的代码运行良好。我在下面重新生成了它。摆脱你正在做的那个不稳定的等待电话。
这样做。创建一个新的uwp应用程序,粘贴下面的代码,在返回上放置一个断点,然后查看它是否被执行。
无论您是否使按钮处理程序异步,它都能工作。如果你不把它作为nyc,那么请求就不会异步执行
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函数可以异步完成这项工作。lib还有许多其他特性。
所以我自己尝试过。不幸的是,您的信息不完整,所以有一个小标题:
对于Json Handling,我使用了Newtonsoft,因为我在UWP环境中没有找到Json.ToObjectAsync
为了创建ExchangeRate
类,我使用了Json2CSharp
以下是汇率类别:
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
-方法更改为async void
。通常不建议使用async void
而不是async Task
。但是,因为它是来自UI元素的处理程序,所以这不是问题,因为源代码无论如何都不会等待,并且您不应该直接从代码后面调用此方法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
-方法中,您需要为异步操作添加一个等待,或者直接在方法后面添加.Wait()
,而不是在新行中。您需要这样做,因为当您调用异步操作并且.Wait()
延迟时,Task会自动开始运行。因此,您的GetJson方法如下所示:
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
}
}
}
此外,我添加了一个检查,如果请求成功,可以肯定的是,我们有响应。我之前说过:我认为应该返回一个ExchangeRat
e-object,而不是一个double,但这取决于您的上下文。