0

我有一个对象集合。在保存这些对象之前,我需要从数据库中获取一些参考数据。我需要为每个对象对数据库进行几次调用。这些方法可以以任何顺序发生/不相互依赖。

我可以async / await用来使这些数据库操作同时发生吗?

Parallel.ForEach(animals,
    animal => {
        animal.Owner = GetAnimalOwner(ownerId);
        animal.FavouriteFood = GetFavouriteFood(foodId);

        Database.Store(animal);
    });

这是一些伪代码,解释了我正在尝试做的事情。这是一个很好的候选人async / await吗?

4

1 回答 1

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. 您想从 UI 线程中卸载一些长时间运行的代码。
  2. 您希望使用更少的线程来提高性能或可伸缩性。

在我看来,#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 Dataflow。

于 2013-07-18T08:34:33.917 回答