- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 .NET 6 项目中,我必须调用偏移分页(页面/每页)的 Web API,并且我希望尽可能使 n 个调用并行。
这是使用给定页码一次调用 API 的方法:
private Task<ApiResponse> CallApiAsync(int page,
CancellationToken cancellationToken = default)
{
return GetFromJsonAsync<ApiResponse>($"...&page={page}", cancellationToken)
.ConfigureAwait(false);
}
我真正需要的是从第 1 页到第 n 页的所有 API 调用的仅向前可流式迭代器,因此鉴于此要求,我认为 IAsyncEnumerable
是正确使用的 API,因此我可以触发API 调用并行调用,并在每个 API 响应准备就绪后立即访问,而无需完成所有响应。
所以我想出了以下代码:
public async IAsyncEnumerable<ApiResponse> CallApiEnumerableAsync(int perPage,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
int numProducts = GetNumberOfProducts(perPage);
int numCalls = MathExtensions.CeilDiv(numProducts, perPage);
var pages = Enumerable.Range(1, numCalls);
Parallel.ForEach(pages, async page => {
yield return await CallApiAsync(page, cancellationToken).ConfigureAwait(false);
});
yield break;
}
但我在 yield
处收到以下错误:CS1621 - yield 语句不能在匿名方法或 lambda 表达式中使用。
有没有办法达到我想要的结果?
如果我不够清楚,请随时提出问题!
最佳答案
您可以为此目的使用的最容易获得的工具是 TransformBlock<TInput,TOutput>
来自 TPL 数据流库。该组件在 .NET Core 及更高版本中 native 可用,它本质上是具有两个队列(输入和输出)的处理器/投影仪/变压器。您指定处理函数,然后根据需要配置选项,然后输入数据,最后检索处理后的输出:
public async IAsyncEnumerable<ApiResponse> CallApiEnumerableAsync(int perPage,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
int numProducts = GetNumberOfProducts(perPage);
int numCalls = MathExtensions.CeilDiv(numProducts, perPage);
var pages = Enumerable.Range(1, numCalls);
TransformBlock<int, ApiResponse> block = new(async page =>
{
return await CallApiAsync(page, cancellationToken);
}, new ExecutionDataflowBlockOptions()
{
CancellationToken = cancellationToken,
MaxDegreeOfParallelism = 10, // Configurable, the default is 1
EnsureOrdered = true, // This is the default
});
// Feed the block with input data
foreach (var page in pages) block.Post(page);
block.Complete();
// Emit the output data as they become available
while (await block.OutputAvailableAsync())
while (block.TryReceive(out var item))
yield return item;
// Propagate possible exception (including cancellation)
await block.Completion;
}
这个简单的实现启动 TransformBlock
当得到 IAsyncEnumerable<ApiResponse>
被枚举,它不会停止,直到所有处理完成,或 cancellationToken
被取消。处理不是由结果序列的枚举驱动。如果客户端代码简单地放弃枚举,它甚至不会停止,break
使用 await foreach
环形。如果你想包含这个功能(优雅终止),你必须添加一个 try
- finally
block 和内部链接 CancellationTokenSource
如图here .屈服循环应放置在 try
内。 ,并取消链接CancellationTokenSource
应该放在finally
里面.
关于c# - 从 IEnumerable<Task<T>> 到 IAsyncEnumerable<T> 通过 yield 在 Parallel.ForEach/Parallel.ForEachAsync 内返回给出错误 CS1621,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73559121/
我预计此代码需要 1 秒才能执行: public async void Test() { DateTime start = DateTime.Now; await Parallel.F
如果我在下面的代码中使用 ForEachAsync,我应该使用列表还是并发集合? var images = new List(); // or a concurrency collection? aw
下面是 ForEachAsync 的实现 written by Stephen Toub . public static Task ForEachAsync(this IEnumerable sour
在 .NET 5 中,我们有 Parallel.ForEach,您可以使用 ParallelLoopState.Break() 方法来停止处理额外的迭代。允许当前的完成处理。 但是新的 .NET 6
我必须对项目列表运行一个函数。我正在使用 Azure Durable Functions,并且可以使用它们的 fan out/fan in 并行运行这些项目。策略。 但是,我想知道这样做与在单个 Ac
我必须对项目列表运行一个函数。我正在使用 Azure Durable Functions,并且可以使用它们的 fan out/fan in 并行运行这些项目。策略。 但是,我想知道这样做与在单个 Ac
我有代码可以从 SQL 流式传输数据并将其写入不同的存储。代码大概是这样的: using (var cmd = new SqlCommand("select * from MyTable", conn
我最近发现下面的代码可以有效地运行大量 I/O 绑定(bind)任务: Implementing a simple ForEachAsync, part 2 我的印象是以下内容是真实的: 这比使用 P
这里是重现的步骤。下面的程序使用 .Net Core 控制台应用程序和 EF Core 将 10,000 行从一个 SQL 表复制到另一个。该程序分 100 批插入记录,并且(这很重要!)它为每次插入
我正在试验如何跳出 ForEachAsync 循环。 break 不起作用,但我可以在 CancellationTokenSource 上调用 Cancel。 ForEachAsync 的签名有两个标
下面应该返回“C”,但它返回“B” using System.Data.Entity; //... var state = "A"; var qry = (from f in db.myTable s
在 .NET 6 项目中,我必须调用偏移分页(页面/每页)的 Web API,并且我希望尽可能使 n 个调用并行。 这是使用给定页码一次调用 API 的方法: private Task CallApi
我是一名优秀的程序员,十分优秀!