这是否适合在此C#.NET代码中使用async await?

时间:2013-07-18 03:17:10

标签: c# .net asynchronous parallel-processing async-await

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

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

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

        Database.Store(animal);
    });

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

1 个答案:

答案 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. 您想要从UI线程中卸载一些长时间运行的代码。
  2. 您希望使用更少的线程来提高性能或可伸缩性。
  3. 在我看来,#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数据流。