【问题标题】:Asynchronously write to an IAsyncEnumerable异步写入 IAsyncEnumerable
【发布时间】:2021-12-29 13:44:21
【问题描述】:

我正在使用 IAsyncEnumerable 从 API 中返回分页结果,如下所示:

public async IAsyncEnumerable<ApiObject> GetResults(){
  int startIndex = 0;
  PaginatedResponse<ApiObject> response;
  do {
    response = await _client.GetResults(_endpoint, startIndex, _pageSize);
    foreach (var obj in response.Items){
      yield return obj;
    }
    startIndex = response.StartIndex + response.Count;
  } while (response.StartIndex + response.Count < response.Total);
}

我想要的是并行发送多个页面的请求,并将每个页面返回到IAsyncEnumerable。顺序无关紧要。

我正在尝试做的事情可能吗?我可以让多个异步任务写入我的方法返回的同一个IAsyncEnumerable 吗?我能想到的最好的办法是让任务写入一个共同的IList,然后在所有任务完成后,遍历该 IList 并返回所有元素:

public async Task<IAsyncEnumerable<ApiObject>> GetResults(){
  int totalPages = _client.MagicGetTotalPagesMethod();
  IList<ApiObject> results = new List<ApiObject>();
  var tasks = Enumerable.Range(0,totalPages).Select(async x => {
    // my goal is to somehow return from here, rather than aggregating into the IList and returning after all tasks are done
    results.AddRange(await _client.GetResults(_endpoint, x*_pageSize, _pageSize));
  });
  await Task.WhenAll(tasks);
  foreach (var result in results){
    yield return result;
  }
}

这个部分通过一次发出多个请求解决了这个问题,但是我们仍然需要等待所有请求都返回,然后这个GetResults 的消费者才能使用结果。 p>

【问题讨论】:

  • “写入可枚举”是什么意思?
  • @Servy 我的目标不是同步。它是异步的。我同时向 API 发送一批请求,然后将每个请求从 API 返回到IAsyncEnumerable。结果的顺序无关紧要。
  • @ewok 没有理由选择将项目添加到列表中。这只是不必要的复杂性。只需让 lambda 返回有问题的值,select 返回的 ienumerable 就是您的值序列
  • @TheodorZoulias 我认为这完全解决了我的问题。谢谢!!!

标签: c# .net .net-core async-await


【解决方案1】:

您可以使用the ability to order a sequence of tasks by completion 使这种方法变得非常简单。

var tasks = Enumerable.Range(0,totalPages).Select(x =>
    client.GetResults(_endpoint, x*_pageSize, _pageSize));

foreach(var task in tasks.Order())
    foreach(var item in await task)
        yield return item;

【讨论】:

  • tasks.Order() 不会阻止所有正在完成的任务吗?如果所有任务尚未完成,如何按完成时间对任务集合进行排序?目标是不阻塞所有正在完成的任务的父方法,而是在一个任务完成后立即从一个任务中返回每个元素,同时等待其余的元素
  • @ewok 您可以查看代码以了解其工作原理。它是异步的,不是同步的,因此不需要阻塞任何任务。
猜你喜欢
  • 2020-04-28
  • 2021-04-30
  • 2020-02-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-03
  • 2017-06-07
  • 1970-01-01
相关资源
最近更新 更多