这两个代码片段使用IQueryable和.AsParallel是等价的吗?

5

我正在处理一些相当基础的TPL代码,遇到了一个情况,我想知道以下两个片段是否等效:

myEnumerable.AsParallel().Select(e =>
{
    //do some work that takes awhile
    return new Thing(e);
}

myEnumerable.Select(e =>
{
    //do some work that takes awhile
    return new Thing(e);
}.AsParallel()

此外,如果它们确实是等效的,它们的等效性是否可以随着IEnumerable扩展方法的TPL接口定义而更改?还是当我更新到.NET V{任何版本}时,我只是在设置自己的代码错误?
背景是,myEnumerable是我尚未枚举(使数据库往返)的EF表(实体)。
我希望的行为是同步进行DB调用,获得一个List返回,并并行操作List(在List中进行一堆Web服务调用)。

1
可以解释一下为什么要给我点踩吗?这样我就可以改进问题了。 - Codeman
3个回答

7
我想知道以下两个代码片段是否等价。
不等价。前一个代码将尝试对IEnumerable进行分区以并行执行。后一个代码将顺序地投影元素到Select,并接收过滤后的IEnumerable。只有AsParallel之后的部分会并行运行。
请注意,LINQ-To-Entities不能真正使用AsParallel。通常,它会使您的代码比顺序执行更慢。此外,DbContext不是线程安全的。那段代码可能会带来更多伤害而不是好处。 您可以先查询数据库,一旦数据在内存中,再使用AsParallel。
我的期望行为是同步进行DB调用,返回一个列表,并并行操作该列表(在列表上进行多个Web服务调用)。
如果要通过返回的数据进行多个Web服务调用,则可以利用现有的自然异步API来进行这些请求。例如,如果您正在查询HTTP端点,则可以利用HttpClient并与async-await结合使用,在不需要任何额外线程的情况下并发执行查询。

很不幸,我没有async-await可用(旧系统和过时的编码标准万岁),但我或许能拼凑出一些类似它的东西来。我会试一试并在几分钟内更新,谢谢! - Codeman
你正在使用哪个版本的.NET框架? - Yuval Itzchakov
4.0,但我不能使用async/await,因为经理担心未来的工程师不会理解它的工作原理。 - Codeman
@Pheonixblade9 告诉那个经理他不用担心 :X。只是为了确认一下,你熟悉 .NET 4.0 的 async-await 支持吗? - Yuval Itzchakov
1
是的,这是我经常使用的东西。不幸的是,咨询业对你施加了一套非常有趣的规则,有时候会让人感到束缚。 - Codeman
显示剩余2条评论

2
只有在 AsParallel 后的内容才是并行的。它之前的所有内容都只是顺序输入流到并行查询中(异常情况:如果输入已经是并行查询,它将被视为这样处理)。
由于 PLINQ 没有解析现有查询的方法,因此无法对其进行并行化。输入是不透明的 IEnumerable

我希望的行为是同步进行 DB 调用,返回一个列表,并以并行方式操作该列表

请使用第一个代码片段。

以并行方式进行大量 Web 服务调用

TPL 在选择 IO 密集型任务的最佳并行度方面效果不佳。使用 WithDegreeOfParallelism 为您特定的 IO 负载选择适当的 DOP。

我不认为我正在使用PLINQ - 只有LINQ-Entities。除非在使用TPL时PLINQ是免费的? - Codeman
1
@Pheonixblade9 PLINQ代表“Parallel LINQ”,它是使用TPL(Task Parallel Library)实现的。当您使用AsParallel时,您正在使用PLINQ。 - Yuval Itzchakov
我知道什么是PLINQ :) 我只是不知道在使用TPL时它是否会自动出现。谢谢! - Codeman

2
不,它们不是等价的。
第一个表达式将在消耗时并行运行Select中的工作。
第二个表达式将在一个线程中运行Select中的工作,以产生用于并行执行的项目。您对第二个表达式进行消耗的操作将并行运行,但这很可能是一些微不足道的东西,无法从并行化中受益。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接