我有一组对象。在保存这些对象之前,我需要从数据库中获取一些参考数据。我需要为每个对象做一些DB调用。这些方法可以按任何顺序发生/不相互依赖。
我可以使用async / await
使这些数据库操作同时发生吗?
Parallel.ForEach(animals,
animal => {
animal.Owner = GetAnimalOwner(ownerId);
animal.FavouriteFood = GetFavouriteFood(foodId);
Database.Store(animal);
});
这是一些伪代码,解释了我正在尝试做什么。
这是async / await
的好候选人吗?
答案 0 :(得分:4)
如果你想要做的就是并行执行这两个操作,那么你不需要async
- await
。您可以使用旧的TPL方法,例如Parallel.Invoke()
:
Parallel.ForEach(animals,
animal => {
Parallel.Invoke(
() => animal.Owner = GetAnimalOwner(ownerId),
() => animal.FavouriteFood = GetFavouriteFood(foodId));
Database.Store(animal);
});
请注意,无法保证这实际上会改善您的效果,具体取决于您的数据库及其与之的连接。
一般来说,async
- await
在两种情况下都有意义:
在我看来,#1不是你的情况。如果您遇到#2,那么您应该将数据库方法重写为真正的异步方法(取决于您的数据库库,这可能是不可能的)。
如果你这样做,那么你可以做类似于Scott Chamberlain建议的事情(但不使用Parallel.ForEach()
):
var tasks = animals.Select(
async animal => {
var getOwnerTask = GetAnimalOwnerAsync(ownerId);
var getFavouriteFoodTask = GetFavouriteFoodAsync(foodId);
animal.Owner = await getOwnerTask;
animal.FavouriteFood = await getFavouriteFoodTask;
await Database.StoreAsync(animal);
});
await Task.WhenAll(tasks);
这将以更大程度的并行性执行,然后Parallel.ForEach()
(因为它受到线程池的限制),但同样,这可能实际上不会提高性能。如果要限制并行度,可以添加SemaphoreSlim
,也可以使用TPL数据流。