我正在尝试将原始代码异步化
for(var item in items)
{
dbAccess.Save(item);
}
工作正常:
var tasks = new List<Task>();
for(var item in items)
{
tasks.Add(dbAccess.SaveAsync(item));
}
await Task.WhenAll(tasks);
但是,在我保存并将项目添加到我的数据库之前,我需要添加一个额外的清理调用:
var tasks = new List<Task>();
for(var item in items)
{
tasks.Add(dbAccess.DeleteAsync(item.id));
tasks.Add(dbAccess.SaveAsync(item));
}
await Task.WhenAll(tasks);
上面的代码不正确,因为在相应的DeleteAsync完成之前不应执行SaveAsync。换句话说,删除必须始终在为每个项目保存之前进行,但项目的顺序无关紧要。
有完美的方法吗?
答案 0 :(得分:6)
创建一个async
方法,对单个项目执行删除,然后执行保存,并对每个项目并行执行所有这些复合操作:
var tasks = items.Select(async item =>
{
await dbAccess.DeleteAsync(item.id);
await dbAccess.SaveAsync(item);
});
await Task.WhenAll(tasks);
答案 1 :(得分:2)
您可以使用Func<Task>
将两个异步调用封装到单个Task
中,如下所示:
for(var item in items)
{
//We store the value of item in a local variable
//because it is not recommended to close over a loop variable
var my_item = item;
Func<Task> task_fact = async () =>
{
await dbAccess.DeleteAsync(my_item.id);
await dbAccess.SaveAsync(my_item);
};
tasks.Add(task_fact());
}
这将创建一个调用delete方法的Task,异步等待它,然后调用save方法并异步等待它。
您可以使用方法执行相同的操作。
答案 2 :(得分:1)
如何使用ContinueWith:
var tasks = new List<Task>();
for(var item in items)
{
var task = dbAccess.DeleteAsync(item.id)
.ContinueWith(antecedent => dbAccess.SaveAsync(item))
.Unwrap();
tasks.Add(task);
}
await Task.WhenAll(tasks);