【发布时间】:2022-01-27 22:12:04
【问题描述】:
我想生成一个可枚举的任务,这些任务将在不同的时间完成。
如何在 C# 中制作一个生成器:
- 产生任务
- 每隔几次迭代,就会解决以前产生的任务,结果现在才知道
我想要这样做的原因是因为我正在处理一个很长的可迭代输入,而且我经常从这些输入中积累足够的数据来发送批处理 API 请求并最终确定我的输出。
伪代码:
IEnumerable<Task<Output>> Process(IEnumerable<Input> inputs)
{
var queuedInputs = Queue<Input>();
var cumulativeLength = 0;
foreach (var input in inputs)
{
yield return waiting task for this input
queuedInputs.Enqueue(input);
cumulativeLength += input.Length;
if (cumulativeLength > 10)
{
cumulativeLength = 0
GetFromAPI(queue).ContinueWith((apiTask) => {
Queue<BatchResult> batchResults = apiTask.Result;
while (queuedInputs.Count > 0)
{
batchResult = batchResults.Dequeue();
historicalInput = queuedInputs.Dequeue();
var output = MakeOutput(historicalInput, batchResult);
resolve earlier input's task with this output
}
});
}
}
}
【问题讨论】:
-
task.ContinueWith(result => ...);方法返回一个任务,在您的示例中被忽略。您真的打算以fire-and-forget 的方式启动延续吗?您是否还知道ContinueWithintricacies 关于TaskScheduler在未提供scheduler参数时默认使用? -
TaskCompletionSource相当于手动创建和解析 Promise。但我不确定你想做什么。 -
@TheodorZoulias 火灾和遗忘有什么问题?我对任何 TaskScheduler 的复杂性一无所知
-
theonlygusti 我在之前的评论中提供了两个链接,它们解释了为什么使用即发即弃和
ContinueWith通常不是一个好主意。我的理解是,您正在尝试使用 C# 做一些在 JavaScript 中很常见的事情,但在 C# 世界中却是惯用且非常规的。无论您尝试做什么,都可能有更好的方法来做到这一点,可能使用IAsyncEnumerable<T>s 和 System.Linq.Async 包或 TPL 数据流库。如果您想要更有针对性的建议,您应该描述您正在尝试解决的更广泛的问题。 -
你可以阅读here微软关于为任务添加
Then方法的意见,这(据我了解)比现有的ContinueWith更接近Javascript的then方法。跨度>
标签: c# async-await task