在 ForEach 循环中链接顺序异步任务:这是一个好方法吗?
Chaining sequential async tasks within a ForEach loop: Is this a good way to do it?
我正在开发一项 windows 服务,我有两个相互依赖的相关调用,我想 运行 异步地为每个 "pair" 或 "set" 的电话。有几种方法可以做到这一点,我尝试了几种不同的方法并解决了这个问题,因为处理一个代码块比处理两个单独的块有自己的 await 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;
}
没有,you should not use 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
method with async/await is not recommended, since the later was invented to replace the former. You could use LINQ 在一行中创建任务,如果您愿意:
Task[] saveBatchTasks = workload.Select(async batchId =>
{
var result = await bll.GetIncomingBatchAsync(batchId);
await bll.SaveIncomingBatchAsync(result);
}).ToArray();
await Task.WhenAll(saveBatchTasks);
我正在开发一项 windows 服务,我有两个相互依赖的相关调用,我想 运行 异步地为每个 "pair" 或 "set" 的电话。有几种方法可以做到这一点,我尝试了几种不同的方法并解决了这个问题,因为处理一个代码块比处理两个单独的块有自己的 await 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;
}
没有,you should not use 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
method with async/await is not recommended, since the later was invented to replace the former. You could use LINQ 在一行中创建任务,如果您愿意:
Task[] saveBatchTasks = workload.Select(async batchId =>
{
var result = await bll.GetIncomingBatchAsync(batchId);
await bll.SaveIncomingBatchAsync(result);
}).ToArray();
await Task.WhenAll(saveBatchTasks);