在 ForEach 循环中链接顺序异步任务:这是这样做的好方法吗?



我正在开发一个Windows服务,我有两个相互依赖的相关调用,我想为每个"对"或"组"调用异步运行。有几种方法可以做到这一点,我已经尝试了一些不同的方法并解决了这个问题,因为有一个代码块来处理很方便,而不是两个单独的块有自己的等待Task.WhenAll()调用。在我的测试中,这似乎按预期工作,但我以前从未像这样将两个任务链接在一起,我想知道这是否是一种好方法,以及是否有更合适的方法来获得相同的结果(单个代码块(。

这是我所拥有的。这看起来像是链接任务的合理方法吗,如果不是,请告诉我原因。

提前谢谢。 -弗兰克

//get all pending batches
foreach (string batchId in workload)
{
try
{
// I am using this ContinueWith pattern here to aggregate the Tasks
// which makes it more convenient to handle exceptions in one place
Task t = bll.GetIncomingBatchAsync(batchId).ContinueWith(
task => bll.SaveIncomingBatchAsync(task.Result),
TaskContinuationOptions.OnlyOnRanToCompletion);
saveBatchTasks.Add(t);
}
catch (Exception ex)
{
_logger.WriteError(ex, "ProcessWorkloadAsync error building saveBatchTasks!");
throw ex;
}
}
try
{
await Task.WhenAll(saveBatchTasks);
}
catch (Exception ex)
{
_logger.WriteError(ex, "ProcessWorkloadAsync error executing saveBatchTasks!");
throw ex;
}

不,您不应该使用ContinueWith。请改用await

如果您担心将逻辑分离到两个函数,只需使用本地函数:

//get all pending batches
foreach (string batchId in workload)
{
try
{
async Task GetAndSave()
{
var result = await bll.GetIncomingBatchAsync(batchId);
await bll.SaveIncomingBatchAsync(result);
}
saveBatchTasks.Add(GetAndSave());
}
catch (Exception ex)
{
_logger.WriteError(ex, "ProcessWorkloadAsync error building saveBatchTasks!");
throw ex;
}
}

通常不建议将老式ContinueWith方法与 async/await 方法结合使用,因为后者是为了取代前者而发明的。如果需要,可以使用 LINQ 在一行中创建任务:

Task[] saveBatchTasks = workload.Select(async batchId =>
{
var result = await bll.GetIncomingBatchAsync(batchId);
await bll.SaveIncomingBatchAsync(result);
}).ToArray();
await Task.WhenAll(saveBatchTasks);

相关内容

  • 没有找到相关文章

最新更新