代码之家  ›  专栏  ›  技术社区  ›  Morse unmounted

uwp在httpclient上等待不工作

  •  0
  • Morse unmounted  · 技术社区  · 6 年前

    我正在尝试从Web 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并获取响应,并且应该为响应分配一些值。相反,在调试时,无论是单步执行还是继续,控件都将退出当前行,并跳过后续行。 (我也把debug放到了下一行),应用程序就冻结了。

    我引用了类似的代码来解析JSON HTTPClient 在stackoverflow和其他博客上,建议使用 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");
    

    不是的副本 httpclient-getasync-never-returns-on-xamarin-android

    • 它不是Xamarin,尽管它是基于C的,但我的代码是不同的,它不是我关心的WebApiclient或GetInformationAsync方法。
    3 回复  |  直到 6 年前
        1
  •  2
  •   Aly Elhaddad    6 年前

    指定的代码有几个错误需要纠正。首先,标记事件处理程序 async :

    private async void Button_Click(object sender, RoutedEventArgs e)
    

    第二,等待 GetJson 由于这是一个异步方法,所以最好在其名称中添加后缀“async”。 ;因此,等待 GetJsonAsync :

    currency_.ROC = await MyClass.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 .

        2
  •  1
  •   DotNetRussell    6 年前

    您的代码工作正常。我在下面重新生成了它。把你正在做的那个不稳定的等待电话处理掉。

    做这个。创建一个新的uwp应用程序,粘贴下面的代码,在返回时放置一个断点,并查看它是否被执行。

    不管您是否使按钮处理程序异步,它都可以工作。但是,如果您不使它成为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;
            }
        }
    }
    

    我能不能利用这一刻,无耻地插上我的自卫队。这对你有用。

    https://github.com/DotNetRussell/UWPLibrary

    BasecodeRequestManager.cs 文件有一个BeginRequest函数,它为您实现异步工作。lib还有许多其他特性。

        3
  •  1
  •   TheTanic Valentine    6 年前

    所以我自己试过。不幸的是,您的信息不完整,所以有一个小标题:
    对于我使用的JSON处理 Newtonsoft 因为我没有找到 Json.ToObjectAsync 在我的UWP环境中。
    创建 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 Task . 但是,因为它是一个来自UI元素的处理程序,所以这不是问题,因为源代码无论如何都不会等待,您不应该直接从代码隐藏中调用这个方法。
    这个 按钮\点击 -方法:

    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()。 迟到了。所以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,但这取决于您的上下文。