HttpClient上的UWP等待不工作



我正在尝试从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.HttpWindows.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本身,也应该等待ReadAsStringAsyncToObjectAsync

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
}
}
}

此外,我添加了一个检查,如果请求成功,可以肯定的是,我们有响应。我之前说过:我认为应该返回一个ExchangeRate-object,而不是一个double,但这取决于您的上下文。

最新更新