【问题标题】:Await in async request webapi 2 client在异步请求 webapi 2 客户端中等待
【发布时间】:2016-02-18 09:39:05
【问题描述】:

我试图了解在 asp.net MVC web api 2 客户端(控制台应用程序)中等待异步操作。我相信我做错了(由于缺乏对等待和异步的理解)。它似乎没有异步运行。这是理解问题的代码

//主函数

static void Main()
{
    RunAsync().Wait();

}

//运行异步

static async Task RunAsync()
{
    using (var client = new HttpClient())
    {
        var apiUrl = ConfigurationManager.AppSettings["apiurl"];
        client.BaseAddress = new Uri(apiUrl);

        ....some code to fetch data

        foreach (var updateObject in updatedata)
        {
            HttpResponse  response = await client.PostAsJsonAsync("webapimethod", updateObject);
            if (response.IsSuccessStatusCode)
            {
                JArray content = await response.Content.ReadAsAsync<JArray>();
            }
        }
    }
}

在上面的代码中,foreach 循环我在循环中以PostAsJsonAsync 调用发出请求,然后我使用ReadAsAsync 来获取响应,但请求始终运行同步。不像被解雇,然后在响应到达时读取数据。

它工作正常,但我希望它是异步的,而不是等待每个请求。如何实现这一点,或者请在这种情况下解释等待异步?尝试阅读博客和文章,但我不明白它是如何工作的。

【问题讨论】:

  • Wait() 使您阻塞线程,直到异步方法完成执行,从而使其同步。请改用await RunAsync()
  • 好的,我明白了,但是 foreach 循环怎么样?
  • 从您的问题看来,您更想并行运行 foreach 吗?在第一个等待PostAsJsonAsync 等时启动第二个?
  • @SSA 这里是关于 foreach 循环中异步的问题:stackoverflow.com/questions/19431494/how-to-use-await-in-a-loop
  • @AlexanderDerck Wait() 在控制台应用程序的 Main 方法中。这是您想要阻止异步调用的非常少数情况之一,否则程序将立即终止。我认为对于这样的应用程序来说,这实际上是一个很好的结构 - 将程序的核心放在异步方法中,除了调用它并在 Main 中阻塞之外什么都不做。

标签: c# asp.net-web-api async-await asp.net-web-api2 dotnet-httpclient


【解决方案1】:

您可能正在寻找的语法是这样的:

public async Task<JArray> GetContentAsync(... updateObject)
{
  HttpResponse  response = await client.PostAsJsonAsync("webapimethod", updateObject);
  if (response.IsSuccessStatusCode)
  {
      return await response.Content.ReadAsAsync<JArray>();
  }
}

由于await 关键字,client.PostAsJsonAsync 正在发生时,GetContentAsync() 方法中的线程将被放回线程池。

然后您可以在调用它的方法中创建所有任务:

var updateData = fetchData();
var tasks = updateData.Select(d => GetContentAsync(d));
var result = (await Task.WhenAll(tasks)).ToList();

Select 将为您的每个结果创建一个任务。 await Task.WhenAll 将解开 Task&lt;JArray&gt; 并创建一个 List&lt;JArray&gt;

【讨论】:

  • 谢谢亚历克斯,现在更有意义了。在 List 中,Result 是 JArray 对的。还有一个问题,当在 foreach 循环 PostAsycJson 中使用 await 时,是什么阻止了它并使其同步运行?有没有办法给每个请求一个回调?在我的代码中,而不是 Task.WhenAll ?就像我们在 javascript 中循环执行 ajax 请求一样。
  • 是的,应该是List&lt;JArray&gt;。在foreach中,你会因为await而释放线程,但是直到一切都完成后它仍然不会进入foreach的下一个循环。最好的办法是为数据中的每个项目创建一个新的Task 并启动这些任务。我通过选择来做到这一点,但你也可以在 foreach 中做到这一点。创建任务不会像你现在的 foreach 那样等到任务完成。
  • 感谢您的及时回复和举例说明。我现在有了更多的见解。
【解决方案2】:

您必须将 foreach 移出 RunAsync 方法。 要让 foreach 循环中的 RunAsync 在异步模式下工作,您必须创建多个任务,然后调用 Task.WaitAll

【讨论】:

    猜你喜欢
    • 2015-07-06
    • 2019-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    相关资源
    最近更新 更多