如何使用 LINQ 等待 ParallelQuery?
How to await a ParallelQuery with LINQ?
我有一个异步方法,它应该查找数据库条目。它按名称过滤,因此是并行执行的候选者。
但是,我找不到同时支持并行执行和异步任务的简单方法。
这是我拥有的:
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()
时它会编译。 A 我不应该同时使用这两个功能?还是我理解有误?
IHMO,两者都有意义:
AsParallel()
表示数据库查询可能会同时拆分为多个子查询 运行,因为任何项目的单独匹配都不依赖于任何其他项目。 更新:这个例子中的坏主意,请参阅评论和回答!
ToListAsync()
将支持异步执行此方法,以允许其他匹配方法(在其他数据上)立即开始执行。
如何同时使用并行执行(使用 LINQ)和异步任务?
嗯,你不能。这是 2 个不同的选项,不能放在一起。
您可以使用 Task.Run
和 async-await
在多个 ThreadPool
线程上并行化异步操作的同步部分(即第一个 await
之前的部分),但没有内置到 PLINQ 中的所有分区逻辑,例如:
var tasks = enumerable.Select(item => Task.Run(async () =>
{
LongSynchronousPart(item);
await AsynchronouPartAsync(item);
}));
await Task.WhenAll(tasks);
然而,在您的情况下(假设它是 Entity Framework),使用 PLINQ 没有任何价值,因为没有实际的并行化工作。查询本身在数据库中执行。
你不能,也不应该。 PLINQ 不适用于数据库访问。数据库最了解如何并行化查询,并使用普通的 LINQ 自行完成。 PLINQ 用于访问对象,例如在 LINQ 查询中进行计算量大的计算,因此它可以在客户端并行化(相对于在 server/database 服务器端并行化)。
更好的答案可能是:
PLINQ 用于跨多个线程分发计算密集型查询。
异步用于 return 返回线程以便其他人可以使用它,因为您将等待外部资源(数据库、磁盘 I/O、网络 I/O 等)。
Async PLINQ 没有非常强大的用例,您希望在等待时 return 线程并且您有很多计算要做...如果您忙于计算,则需要线程(或多个线程)。它们几乎完全处于优化的不同端。如果你需要这样的东西,有更好的机制,如任务等。
我有一个异步方法,它应该查找数据库条目。它按名称过滤,因此是并行执行的候选者。
但是,我找不到同时支持并行执行和异步任务的简单方法。
这是我拥有的:
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()
时它会编译。 A 我不应该同时使用这两个功能?还是我理解有误?
IHMO,两者都有意义:
AsParallel()
表示数据库查询可能会同时拆分为多个子查询 运行,因为任何项目的单独匹配都不依赖于任何其他项目。 更新:这个例子中的坏主意,请参阅评论和回答!ToListAsync()
将支持异步执行此方法,以允许其他匹配方法(在其他数据上)立即开始执行。
如何同时使用并行执行(使用 LINQ)和异步任务?
嗯,你不能。这是 2 个不同的选项,不能放在一起。
您可以使用 Task.Run
和 async-await
在多个 ThreadPool
线程上并行化异步操作的同步部分(即第一个 await
之前的部分),但没有内置到 PLINQ 中的所有分区逻辑,例如:
var tasks = enumerable.Select(item => Task.Run(async () =>
{
LongSynchronousPart(item);
await AsynchronouPartAsync(item);
}));
await Task.WhenAll(tasks);
然而,在您的情况下(假设它是 Entity Framework),使用 PLINQ 没有任何价值,因为没有实际的并行化工作。查询本身在数据库中执行。
你不能,也不应该。 PLINQ 不适用于数据库访问。数据库最了解如何并行化查询,并使用普通的 LINQ 自行完成。 PLINQ 用于访问对象,例如在 LINQ 查询中进行计算量大的计算,因此它可以在客户端并行化(相对于在 server/database 服务器端并行化)。
更好的答案可能是: PLINQ 用于跨多个线程分发计算密集型查询。 异步用于 return 返回线程以便其他人可以使用它,因为您将等待外部资源(数据库、磁盘 I/O、网络 I/O 等)。
Async PLINQ 没有非常强大的用例,您希望在等待时 return 线程并且您有很多计算要做...如果您忙于计算,则需要线程(或多个线程)。它们几乎完全处于优化的不同端。如果你需要这样的东西,有更好的机制,如任务等。