Linq并行执行
一、 并行LINQ
- 1. 并行查询
.NET4在System.Linq名称空间中包含一个新类ParalleIEnumerable ,可以分解查询的工作使其分布在多个线程上。尽管Enmerable类给IEnunerable<T>接口定义了扩展方法,但
ParalleIEnumerable 类的大多数扩展方法是ParallelQuery<TSource>类的扩展。一个重要的例外是AsParallel()方法,它扩展了IEnumerable<TSource>接口,返回ParallelQuery<TSource>类,所以正常的集合类可以以平行方式查询。
例:
const int arraySize = 100000000;
var data = new int[arraySize];
var r = new Random();
for (int i = 0; i < arraySize; i++)
{
data[i] = r.Next(40);
}
现在可以使用LINQ查询筛选数据,获取筛选数据的总和。该查询用where子句定义了一个筛选器,仅会中对应值小于20的项,接着调用聚合函数Sum()方法 。与前面的LINQ查询的唯一区别是,这次调用了AsParallel()方法。
var sum = (from x in data.AsParallel()
where x < 20
select x).Sum();
与前面的LINQ查询一样,编译器会修改语法,以调用AsParallel()、Where()、Select()和Sum()方法。AsParallel()方法用ParallelEnumerable类定义,以扩展IEnumerable<T>接口,所以对简单的数据调用它。AsParallel()方法返回ParallelQuery<TSource>。因为返回的类型,所以编译器选择的Where()方法是ParallelEnumerable.Where(),而不是Enumerable.Where()。在下面的代码中Select()和Sum()方法也来自ParallelEnumerable类。与Enumerable类的实现代码相反,对于ParallelEnumerable类,查询是分区的,以便多个线程可以同时处理该查询。数组可以分为多个部分,其中每个部分由不同的线程处理,以筛选其余项。完成分区的工作后,就需要合并,获得所有部分的总和。
var sum=data.AsParallel().Where(x=>x<20).Select(x=>x).Sum();
运行这行代码就会启动任务管理器,这样就可以看出系统的所有CPU都在忙碌。如果删除AsParallel()方法,就不可能使用多个CPU。当然,如果系统上没有多个CPU,就不会看到并行版本带来改进。
- 2. 分区器
AsParallel()方法不仅扩展了IEnumerable<T>接口,还扩展了Partition类。通过它,可以影响要创建的分区。
Partitioner类用System.Collection.Concurrent命名空间定义,并且有不同变体。Create方法接受实现了IList<T>类的数组或对象。根据这一点,以及类型的参数loadBalance和该方法的一些重载版本,会返回一个不同的Partitioner类型。对于数组,.Net4包含派生自抽象基类OrderablePartitioner<TSource>的DynamicPartitionerForArray<TSource>类和StaticPartitionerForArray<TSource>类。
var q1 = (from x in Partitioner.Create(data).AsParallel()
where x < 20
select x).Sum();
也可以调用WithExecutionMode()和WithDegreeOfParallelism()方法可以传递ParallelExecutionMode的一个Default值或者ForceParallelism值。默认情况下,并行LINQ避免使用系统开销很高的并行机制。对于WithDegreeOfParallelism()方法,可以传递一个整数值,以指定并行运行的最大任务数。
例:
const int arraySize = 100000000;
var data = new int[arraySize];
var r = new Random();
for (int i = 0; i < arraySize; i++)
{
data[i] = r.Next(40);
}
Stopwatch watch = new Stopwatch();
watch.Start();
//一种写法,没有添加动态负载均衡,执行完所需要的时间1300毫秒
var q1 = (from x in Partitioner.Create(data).AsParallel()
where x < 80
select x).Sum();
//第二种写法,添加了动态负载均衡,执行完所需要的时间为660毫秒。
var q1 = (from x in Partitioner.Create(data,true).AsParallel()
where x < 80
select x).Sum();
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds.ToString());
- 3. 取消
.Net提供了一种标准方式,来取消长时间运行的任务,这也适用于并行LINQ。要取消长时间的查询,可以给查询添加WithCancellation()方法,并传递一个CancellationToken令牌作为参数。CancellationToken令牌从CancellationTokenSource类中创建。该查询在单独的线程中运行,在该线程中,捕获一个OperationCancelException类型的异常。如果取消了查询,就触发这个异常。在主线程中,调用CancellationTokenSource类的Cancel()方法可以取消任务。
const int arraySize = 100000000;
var data = new int[arraySize];
var r = new Random();
for (int i = 0; i < arraySize; i++)
{
data[i] = r.Next(40);
}
var cts = new CancellationTokenSource();
new Thread(() =>
{
try
{
var sum = (from x in data.AsParallel().WithCancellation(cts.Token)
where x < 80
select x).Sum();
Console.WriteLine("query finished, sum: {0}", sum);
}
catch (OperationCanceledException ex)
{
Console.WriteLine(ex.Message);
}
}).Start();
Console.WriteLine("query started");
Console.Write("cancel? ");
int input = Console.Read();
if (input == 'Y' || input == 'y')
{
// cancel!
cts.Cancel();
}
Linq并行执行的更多相关文章
- 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)
Task - 基于线程池的任务(在 System.Threading.Tasks 命名空间下) 多 Task 的并行执行 Parallel - 并行计算(在 System.Threading.Task ...
- 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)
[源码下载] 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel) 作者:webabcd 介绍重新想象 W ...
- .net LINQ and PLINQ
本文 学习自 微软官网文档 2016/12 LINQ 背景 以前写与DB 相关的代码, 程序员须要懂开发语言(C#, VB)和查询语言跟数据库交互. LINQ 的出现使应用程序形成基于集合 ...
- .Net多线程编程—Parallel LINQ、线程池
Parallel LINQ 1 System.Linq.ParallelEnumerable 重要方法概览: 1)public static ParallelQuery<TSource> ...
- [C#]一个简易的、轻量级的方法并行执行线程辅助类
一个简易的.轻量级的方法并行执行线程辅助类 在实际应用中,经常要让多个方法并行执行以节约运行时间,线程就是必不可少的了,而多线程的管理经常又是一件头疼的事情,比如方法并行执行异步的返回问题,方法并 ...
- 扩展、委托、Lambda、linq
1.扩展 扩展是一个很有用的功能.如果你有一个类.不能修改,同时你又想给他加一个方法.这个过程就是扩展.扩展就是扩展方法. 例1: 类People public class People { publ ...
- PLINQ 并行操作Linq
C#并行编程-PLINQ:声明式数据并行 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C#并行编程-线程同步原语 C#并行编程-P ...
- Linq表达式、Lambda表达式你更喜欢哪个?
什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
随机推荐
- 关于Kendo的Grid 单元格样式
<!DOCTYPE html><html style="height: 100%;"><head><meta http-equiv=&qu ...
- Java JDBC使用方法
public class JDBC{public static void main(String[] args){//查询数据selectData();}//查询数据的方法private static ...
- JVM加载类的过程,双亲委派机制中的方法
JVM加载类的过程: 1)JVM中类的整个生命周期: 加载=>验证=>准备=>解析=>初始化=>使用=>卸载 1.1.加载 类的加载阶段,主要是获取定义此类的二进 ...
- js取整函数
1.丢弃小数部分,保留整数部分parseInt(5/2) 2.向上取整,有小数就整数部分加1 Math.ceil(5/2) 3,四舍五入. Math.round(5/2) 4,向下取整 Math.fl ...
- JSBinding / Testing
Unity version compatibilities 5.3.5 5.2.0 5.1.5 5.0.4 4.7.2 4.7.0 4.6.9 4.6.0 4.5.5 Platform compati ...
- CDN 技术详解(DNS,GSLB,Cache)
CDN 是什么 CDN(Content Delivery Network,内容分发网络),即全网内容加速服务.为了尽可能的避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快.更稳 ...
- linux yum命令详解-转
yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器.基於RPM包管理,能够从指定的服务器自动下载RP ...
- 数据绑定时(<%#Eval)单引号双引号嵌套问题
期望得到的HTML如下: onclick='edit("10000001")' 或者 onclick="edit('10000001')" 实际ASP.NET前 ...
- C# 随机红包算法
static void Main(string[] args) { ; ; double minAmount = 0.01; Random r = new Random(); ; i < num ...
- spread 程序调试时,未激活的提示解决
场景:程序调试运行,打开含spread组件的窗体时如下: 解决: 将spread组件拖到某一个窗体后,会在properties中出现license文件.再运行,OK! 注意: license文件一定是 ...