我有一个异步方法,应该查找数据库条目。它按名称过滤,因此是并行执行的候选者。
但是,我找不到支持并行执行和异步任务的简单方法。
以下是我所拥有的:
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)和异步任务?
答案 0 :(得分:3)
你不能,也不应该。 PLINQ不适用于数据库访问。数据库最了解如何并行化查询,并使用普通LINQ对它自己做得很好。 PLINQ用于访问对象,例如在LINQ查询中进行计算成本高的计算,因此它可以在客户端进行并行化(与在服务器/数据库服务器端并行化)。
更好的答案可能是: PLINQ用于分发跨多个线程计算密集的查询。 Async用于返回线程,以便其他人可以使用它,因为您将等待外部资源(数据库,磁盘I / O,网络I / O等)。
Async PLINQ没有一个非常强大的用例,你想在等待时返回线程并且你有很多计算要做...如果你忙于计算,你需要线程(或者多线程)。它们几乎完全处于优化的不同端。如果您需要这样的东西,那么有更好的机制,如任务等。
答案 1 :(得分:0)
您可以使用Task.Run
和async-await
来并行化多个await
线程上的异步操作的同步部分(即第一个ThreadPool
之前的内容),但是没有PLINQ中内置的所有分区逻辑,例如:
var tasks = enumerable.Select(item => Task.Run(async () =>
{
LongSynchronousPart(item);
await AsynchronouPartAsync(item);
}));
await Task.WhenAll(tasks);
然而,在你的情况下(假设它是实体框架),使用PLINQ没有价值,因为没有实际的并行工作。查询本身在DB中执行。