1、简介

关于并行Linq,Ms官方叫做并行语言集成(PLINQ)查询,其实本质就是Linq的多线程版本,常规的Linq是单线程的,也就是同步的过程处理完所有的查询.如果你的Linq查询足够简单,而且耗时短,那么建议你使用Linq,但是如果你的查询比较耗时,而且很复杂,且不涉及多线程争用问题,那么可以使用PLinq技术,让多个线程参与到查询中来,有效的利用CPU资源.这样你的代码能从中获得最大的收益.判断什么时候使用PLINQ,什么时候使用Linq?这需要你自己去实践,因为不同的环境,产生的效果不一样,因为我前面的随笔中介绍了,多线程(Task,因为Parallel是基于Task的)本身的开销,CPU的上下文切换,都是影响的因素.可能你使用PLINQ执行一个复杂的查询,本地的运行速度很快,但是放到服务器上去反而变慢了.所以使用还是需要慎重.

2、代码结构简介

(1)、基本Api介绍

那么如何使用PLINQ呢?所有的PLINQ的Api都在System.Linq.ParallelEnumerable类下面,Api几乎和Linq一样,因为内容太多,这里就不截图了.MS几乎将常规的LINQ所有的Api都实现了一个并行版本.所有的方法都是ParallelQuery<TSource>类型的扩展,如下:

所有如果你有一个常规集合需要进行并行查询,那么你需要将该集合转换成ParallelQuery<TSource>类型,MS提供了转换方法,如下:

主要是红框中的两个,一个泛型版本,一个非泛型版本,本文主要介绍这两个,其余的稍微介绍下.

:调用这个方法,它将执行并行查询切换为同步查询,但是不常用.

调用这个方法,线程将成组处理数据,然后将数据项合并回去,同时保持顺序,会产生一定的性能损耗.

注:如果你调用的不是对数据源进行排序的方法,那么它们的并行处理结果是无序的,每次都会变,但是如果你希望有序之后变无序,可以调用但是没有人会这么干!

(2)、构造可取消的PLINQ查询

接受一个CancellationToken参数,支持显示取消.

(3)、构造线程数限制的PLINQ查询

接受一个最大的可分配线程数参数,一般小于内核数.

(4)、构造一个强制以并行方式执行的PLINQ查询

因为并不并行,是PLINQ内部机制决定的,所以可能你的查询过于简单,它会以并行的方式处理,所以如果你需要强制它以并行方式执行可以调用

并给后面的枚举设置

(5)、指定多个线程处理完数据源后已何种方式合并处理完的数据项

指定不同的枚举项,会对性能产生影响。建议你每个都是试一试,就知道哪个更适合你的接口.一般默认的就够了.因为PLINQ调度内核的方式很复杂,所以这里不多介绍.

3、实战

将一个模块程序集中的所有查询接口和查询实体放到一个实例中,并返回.

User模块的代码结构如下:

    class ParallelLinqStudy
{
static void Main(string[] args)
{ var modules=Register("User");
Console.ReadKey();
}
static object lockObjOne = new object();
static object lockObjTwo = new object();
static ModultInfo Register(params string[] assembies)
{
var moduleInfo = new ModultInfo();
assembies.ForEach(assembly =>
{
var ass=Assembly.Load(assembly);
var allTypes = ass.GetTypes().AsParallel();
//遍历传入程序集,将所有实现了IQuery接口的接口类型,并将其在控制台上输出
allTypes.Where(w => w.ImplInterfance<IQuery>()).Where(w => w.IsInterface && w.Name!= "IQuery").ForEach(f =>
{
lock (lockObjOne)
{
moduleInfo.IQueries.Add(f);
}
allTypes.Where(w => f.IsAssignableFrom(w) && !w.IsInterface).ForEach(type =>
{
lock (lockObjTwo)
{
moduleInfo.Queries.Add(type);
}
});
});
});
return moduleInfo;
}
} class ModultInfo
{
public List<Type> IQueries { get; set; } = new List<Type>(); public List<Type> Queries { get; set; } = new List<Type>();
} /// <summary>
/// Type扩展
/// </summary>
static class TypeExtension
{
/// <summary>
/// 判断传入类型type是否实现了Interface接口
/// </summary>
/// <typeparam name="Interface"></typeparam>
/// <param name="type"></param>
/// <returns></returns>
public static bool ImplInterfance<Interface>(this Type type)
{
//接口实例是可以分配给实现类型的,而实例是不可以分配给接口实例的
return typeof(Interface).IsAssignableFrom(type);
}
} /// <summary>
/// Linq扩展
/// </summary>
static class LinqExtension
{
public static void ForEach<T>(this IEnumerable<T> enumerators, Action<T> action)
{
foreach (var item in enumerators)
{
action(item);
}
}
}

上面的代码给List加了锁,因为它是线程不安全的,具体请参考我的这篇随笔

ok,现在拿到了所有的Query接口和Query实体,如果后续需要对这两个集合进行后续的只读操作,可以使用Parallel(参考我前面的随笔)进行并行的只读操作,如果操作很耗时,或者很复杂.也可以将集合转换为ParallelQuery<TSource>类型,并使用

方法进行后续的并行操作.代码如下:

        static void Main(string[] args)
{
var modules = Register("User");
modules.IQueries.AsParallel().ForAll(iQuery =>
{
//执行一个不带返回值的操作
});
Console.ReadKey();
}

C# 多线程八之并行Linq(ParallelEnumerable)的更多相关文章

  1. C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是TAP(Task-based Asynchronous Pattern, 基于任务的异步模式)

    学习书籍: <C#本质论> 1--C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是 ...

  2. C#编程(六十三)----------并行LINQ

    并行LINQ .NET4在System.Linq命名空间中包含一个新类ParallelEnumerable,可以分解查询的工作使其分布在多个线程上.尽管Enumerable类给IEnumerable& ...

  3. 四、并行编程 - 并行LINQ(PLINQ) 的使用。AsParallel

    用于对内存中的数据做并行运算,也就是说其只支持 LINQ to Object 的并行运算 一.AsParallel(并行化) 就是在集合后加个AsParallel(). 例如: , ); == ); ...

  4. 并行Linq(一)

    .Net 并行计算 ----并行Linq(一) 本文是.Net 并行计算 的第三篇 欢迎大家拍砖,阅读本文需要有LINQ基础,因为并行LINQ (PLinq) 其实是LINQ To Object 的并 ...

  5. 并行Linq

    有时候我们对大批量数据进行处理,此时并行linq就起作用了. 并行查询 对于以下查询可以耗时会非常大,如下: ; var r = new Random(); , arraySize).Select(x ...

  6. C#编程(五十八)----------并行集合

    并行集合 对于并行任务,与其相关紧密的就是对一些共享资源,数据结构的并行访问.经常要做的就是对一些队列进行加锁-解锁,然后执行类似插入,删除等等互斥操作. .NET4提供了一些封装好的支持并行操作数据 ...

  7. java网络编程——多线程数据收发并行

    基本介绍与思路 收发并行 前一篇博客中,完成了客户端与服务端的简单TCP交互,但这种交互是触发式的:客户端发送一条消息,服务端收到后再回送一条.没有做到收发并行.收发并行的字面意思很容易理解,即数据的 ...

  8. 谈谈C#多线程开发:并行、并发与异步编程

    阅读导航 一.使用Task 二.并行编程 三.线程同步 四.异步编程模型 五.多线程数据安全 六.异常处理 概述 现代程序开发过程中不可避免会使用到多线程相关的技术,之所以要使用多线程,主要原因或目的 ...

  9. Java多线程——<八>多线程其他概念

    一.概述 到第八节,就把多线程基本的概念都说完了.把前面的所有文章加连接在此: Java多线程——<一>概述.定义任务 Java多线程——<二>将任务交给线程,线程声明及启动 ...

随机推荐

  1. java基础-day32

    第09天 JDBC连接池&DBUtils工具类 今日内容介绍 u c3p0连接池 u dbcp连接池 u DBUtils工具类 第1章   c3p0连接池 1.1  连接池概述 实际开发中“获 ...

  2. set_time_limit

    语法 : void set_time_limit (int seconds)说明 : 设定一个程式所允许执行的秒数,如果到达限制的时间,程式将会传回错误.它预设的限制时间是30秒,max_execut ...

  3. python 的 字节码 导入使用

    1. python 模块文件可以通过编译为字节码的形式: 名字:model.py x = def funt(): import model print(model.x) x = "zhang ...

  4. hdu 4937 base进制只含3456的base数

    http://acm.hdu.edu.cn/showproblem.php?pid=4937 给定一个数n,若这个数在base进制下全由3,4,5,6组成的话,则称base为n的幸运进制,给定n,求有 ...

  5. 冲刺博客NO.2

    今日做了什么:   了解到Mob.com有全球短信验证功能,按照官方集成文档下载了SDK,但是还不会写(正在慕课网上学习). 掌握了android开发的一些流程,熟悉了android studio的语 ...

  6. csv 文件读取(input)和截分(split)方法

    下面是宝玉对学生的指导

  7. Sql Server Report 导出到EXCEL 指定行高

    在SQL SERVER REPORT 2005做报表的时候,发现在report中指定的行高没有用.google了一下,找到了解决方法. Make both CanGrow and CanShrink ...

  8. Asp.Net Core探索 之 appsettings.json

    appsettings.json是什么? 相信大家在.Net Framework的项目都会用的web.config,app.config这些文件,appsettings.json文件就是Asp.Net ...

  9. 【转】Windows Server 2016 安装 IIS 服务时提示指定备用源路径

    原文地址:http://www.codingwhy.com/view/973.html 在Windows Serever 2016中安装IIS的时候,遇到以下提示 是否需要指定备用源路径?一个或多个安 ...

  10. [luogu 5301][bzoj 5503] [GXOI/GZOI2019] 宝牌一大堆

    题面 好像ZJOI也考了一道麻将, 这是要发扬中华民族的赌博传统吗??? 暴搜都不会打, 看到题目就自闭了, 考完出来之后看题解, \(dp\), 可惜自己想不出来... 对于国士无双(脑子中闪过了韩 ...