如何使用LINQ等待ParallelQuery?

时间:2015-05-15 14:32:41

标签: linq asynchronous async-await parallel-extensions

我有一个异步方法,应该查找数据库条目。它按名称过滤,因此是并行执行的候选者。

但是,我找不到支持并行执行和异步任务的简单方法。

以下是我所拥有的:

private async Task<List<Item>> GetMatchingItems(string name) {
    using (var entities = new Entities()) {
        var items =  from item in entities.Item.AsParallel()
               where item.Name.Contains(name)
               select item;
        return await items.ToListAsync(); //complains "ParallelQuery<Item> does not contain a definition for ToListAsync..."
    }
}

当我删除AsParallel()时,它将编译。我不应该同时使用这两个功能?或者我是否理解错误?

IHMO,都有道理:

  • AsParallel()表示数据库查询可能会被拆分为同时运行的多个子查询,因为任何项目的个别匹配都不依赖于任何其他项目。 更新:此示例中的错误主意,请参阅评论和回答!
  • ToListAsync()将支持此方法的异步执行,以允许其他匹配方法(对其他数据)立即开始执行。

如何同时使用并行执行(使用LINQ)和异步任务?

2 个答案:

答案 0 :(得分:3)

你不能,也不应该。 PLINQ不适用于数据库访问。数据库最了解如何并行化查询,并使用普通LINQ对它自己做得很好。 PLINQ用于访问对象,例如在LINQ查询中进行计算成本高的计算,因此它可以在客户端进行并行化(与在服务器/数据库服务器端并行化)。

更好的答案可能是: PLINQ用于分发跨多个线程计算密集的查询。 Async用于返回线程,以便其他人可以使用它,因为您将等待外部资源(数据库,磁盘I / O,网络I / O等)。

Async PLINQ没有一个非常强大的用例,你想在等待时返回线程并且你有很多计算要做...如果你忙于计算,你需要线程(或者多线程)。它们几乎完全处于优化的不同端。如果您需要这样的东西,那么有更好的机制,如任务等。

答案 1 :(得分:0)

嗯,你不能。这些是两个不同的选项。

您可以使用Task.Runasync-await来并行化多个await线程上的异步操作的同步部分(即第一个ThreadPool之前的内容),但是没有PLINQ中内置的所有分区逻辑,例如:

var tasks = enumerable.Select(item => Task.Run(async () => 
{
    LongSynchronousPart(item);
    await AsynchronouPartAsync(item);
}));
await Task.WhenAll(tasks);

然而,在你的情况下(假设它是实体框架),使用PLINQ没有价值,因为没有实际的并行工作。查询本身在DB中执行。