【问题标题】:How do I correctly use HttpClient with async/await?如何正确使用 HttpClient 和 async/await?
【发布时间】:2015-06-28 17:38:38
【问题描述】:

以下代码出现两个错误:

public async Task<string> TestDownloadTask()
{
    HttpResponseMessage response = null;

    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri(@"https://api.nasa.gov/planetary/apod");
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        response.EnsureSuccessStatusCode();
        response = await client.GetStringAsync("?concept_tags=True&api_key=DEMO_KEY");
    }

    return response.Content;
}

我明白了:

  • 无法在“await”行等待“System.Threading.Tasks.Task”
  • 无法将表达式类型“System.Net.Http.Content”转换为返回类型“字符串”

我一直在尝试编写将从 Web 服务下载字符串的上述代码,但关于如何使用 async 和 await 以及如何使用 HttpClient 似乎有很多相互矛盾的信息,我不知道我写的代码有什么问题。

我哪里出错了,我应该怎么做?

【问题讨论】:

  • 您确定这是您遇到的错误吗? GetStringAsync 返回一个Task&lt;string&gt;,并且您试图将结果分配给HttpResponseMessage 类型的变量,因此您的代码肯定由于类型不匹配而损坏,但您似乎不太可能收到错误消息“不能等待System.Threading.Tasks.Task”。

标签: c# async-await task-parallel-library


【解决方案1】:

这个方法client.GetStringAsync返回Task&lt;string&gt;

public Task<string> TestDownloadTask()
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri(@"https://api.nasa.gov/planetary/apod");
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        // You don't need await here
        return client.GetStringAsync("?concept_tags=True&api_key=DEMO_KEY");
    }
}

使用上述功能:

public async void SomeMethod()
{
    // await to get string content
    string mystring = await TestDownloadTask();
}

【讨论】:

  • 我一头雾水,难道不需要HttpResponseMessage吗?
  • 是的。不需要 HttpResponseMessage,GetStringAsync 返回字符串
  • @user9993 HttpResponseMessage 不是魔法咒语。如果您从调用的任何方法中获取HttpResponseMessage 并且需要将其存储在变量中,那么您需要HttpResponseMessage 变量。否则你就不需要了。
  • @Asad 没错,只是互联网上糟糕且相互矛盾的信息让人难以理解。
  • @user9993 使用静态类型语言的好处之一是您可以将类型系统本身用作文档(如果您有一个好的 IDE,例如 Visual Studio),而忽略在线文档。如果你右击GetStringAsync并选择go to definition,你应该能够看到该方法想要什么以及它返回什么。
【解决方案2】:

更改为

return await client.GetStringAsync("?concept_tags=True&api_key=DEMO_KEY");

或到

return await response.Content.ReadAsStringAsync();

【讨论】:

  • 有什么区别,什么时候应该使用一个而不是另一个?
  • response.ContentHttpContent 类型,它不仅可以表示字符串,还可以表示例如字节数组,如果您想下载文件。在你的情况下没有区别。
猜你喜欢
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
  • 2013-10-02
  • 2022-01-07
相关资源
最近更新 更多