本随笔续接:.NET 实现并行的几种方式(二)

在前两篇随笔中,先后介绍了 Thread 、ThreadPool 、IAsyncResult (即 APM系列) 、Task 、TPL (Task Parallel Library)

写到这些笔者突然意识到 还有一个EMP系列没有写,在这里补充一下:

六、 EAP 、EAP中的典型代表是 WebClient:

EAP系列采用 ***Async方法 + ***Completed事件 的编码规范,不做太多解释、具体的demo如下:

            var address = "http://www.cnblogs.com/08shiyan/";

            WebClient client = new WebClient();
Uri uri = new Uri(address); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler((object sender, DownloadStringCompletedEventArgs e) =>
{
this.txtTip.SetTip("下载完成");
}); client.DownloadStringAsync(uri); this.txtTip.SetTip("开始异步下载数据");

WebClient

七、PLINQLINQ的并行版本

1) 首先看一下PLINQ在 MSDN 中的介绍 :

并行 LINQ (PLINQ) 是 LINQ 模式的并行实现。 PLINQ 查询在许多方面类似于非并行 LINQ to Objects 查询。 与顺序 LINQ 查询一样,PLINQ 查询对任何内存中 IEnumerable 或 IEnumerable<T> 数据源进行操作,并推迟执行,这意味着在枚举查询之前不会开始执行这些操作。 主要区别是 PLINQ 尝试充分利用系统中的所有处理器。 它利用所有处理器的方法是,将数据源分成片段,然后在多个处理器上对单独工作线程上的每个片段并行执行查询。 在许多情况下,并行执行意味着查询运行速度显著提高。

通过并行执行,PLINQ 通常只需向数据源添加 AsParallel 查询操作,即可在某些查询类型的旧版代码上获得显著的性能改进。 但是,并行可能引入其自己的复杂性,因此并非所有查询操作在 PLINQ 中都运行得更快。 事实上,并行降低了某些查询的速度。 因此,您应了解诸如排序等问题如何影响并行查询。 有关详细信息,请参阅 Understanding Speedup in PLINQ

从介绍中、我们可以明确三点:

1、PLINQ是LINQ的并行版本、它拥有和LINQ一样一样强大的基因。

2、PLINQ会尝试充分利用所有处理器、(PLINQ在 MSDN 中的介绍 最多是64个),因此许多情况下PLINQ可以显著提高的并行效率,尤其是CPU密集型计算的并行率。

3、并非所有查询操作在 PLINQ 中都运行得更快。

2)PLINQ与LINQ的无缝连接

PLINQ 的实现基础是 :ParallelQuery<TSource>,LINQ的实现基础是:IEnumerable<TSource>, 当然这里说的都是泛型版本。

如下的两个扩展方法、可轻易实现PLINQ和LINQ间的转化。

public static ParallelQuery<TSource> AsParallel<TSource>(this IEnumerable<TSource> source);
public static IEnumerable<TSource> AsSequential<TSource>(this ParallelQuery<TSource> source);

3)简单Demo

        /// <summary>
/// PLinq:Linq的并行版本
/// </summary>
public void Demo1()
{
Task.Run(() =>
{
var result = Enumerable.Range(, ).AsParallel().Where(e =>
{
SetTip("开始 " + e); SetTip("休眠 " + e);
Thread.Sleep(); SetTip("结束 " + e);
return e > ;
}); SetTip("打印结果"); foreach (var item in result)
{
SetTip(item.ToString());
} SetTip("并行查询执行完毕");
});
}

PLinq:Linq的并行版本

4)PLINQ与LINQ的微妙关系

在功能上:PLINQ几乎实现了LINQ的全部功能、且方法名都是一致的。

在时间性能上:PLINQ will always attempt to execute a query at least as fast as the query would run sequentially.

  因此、PLINQ在执行查询之前会进行一次“预判”,如果发现了某些情况,当前可能会自动转为顺序执行、即LINQ模式。

5)当查询包含以下情况时,PLINQ将会默认按照顺序模式执行

  • 包含 Select 子句、已建立索引的 Where 子句、已建立索引的 SelectMany 子句或 ElementAt 子句的查询(在排序或筛选运算符移除或重新排列了索引后)。

  • 包含 Take、TakeWhile、Skip、SkipWhile 运算符并且源序列中的索引未采用原始顺序的查询。

  • 包含 Zip 或 SequenceEquals 的查询,除非其中一个数据源具有按原始顺序排列的索引,并且另一个数据源可建立索引 (例如:数组 或 IList(T)).

  • 包含 Concat 的查询,除非将其应用到可建立索引的数据源。

  • 包含 Reverse 的查询,除非应用到可建立索引的数据源。

6) 强制PLINQ并行查询

我们可以通过 WithExecutionMode<TSource> 运算符,指定 ParallelExecutionMode.ForceParallelism  强制PLINQ并行查询。

7)ForAll多线程枚举

你有可能对“多线程枚举”这个词感到莫名其妙,先看图:

如果你用 foreach、即 IEnumerable 接口枚举并行查询结果,其流程图如第一个所示:即多个线程并行完成后,

还会有一个Merger操作,使结果回到使用该数据的主线程、并将数据合并。

而 ForAll是并行版本的Foreach.

8)其他运算符

1、AsOrdered<TSource>  PLINQ查询默认是不保留顺序的。该运算符可保留源序列的顺序(会产生额外的排序开销、降低性能)。

2、AsUnordered<TSource>  是 AsOrdered<TSource>的反操作、对后续操作不在保持序列,可用于中间查询、提高性能。

  AsUnordered can be called anywhere in the query; it does not need to be called immediately after AsParallel.

3、WithCancellation<TSource> 用于取消操作

4、WithDegreeOfParallelism<TSource>   用以指定最大可使用的处理器数量。

9)补充:影响PLINQ查询性能的因素

附,Demo : http://files.cnblogs.com/files/08shiyan/ParallelDemo.zip

参见更多:随笔导读:同步与异步

(未完待续...)

.NET 实现并行的几种方式(三)的更多相关文章

  1. .NET 实现并行的几种方式(四)

    本随笔续接:.NET 实现并行的几种方式(三) 八.await.async - 异步方法的秘密武器 1) 使用async修饰符 和 await运算符 轻易实现异步方法 前三篇随笔已经介绍了多种方式.利 ...

  2. .NET 实现并行的几种方式(二)

    本随笔续接:.NET 实现并行的几种方式(一) 四.Task 3)Task.NET 4.5 中的简易方式 在上篇随笔中,两个Demo使用的是 .NET 4.0 中的方式,代码写起来略显麻烦,这不 .N ...

  3. .NET 实现并行的几种方式(一)

    好久没有更新了,今天来一篇,算是<同步与异步>系列的开篇吧,加油,坚持下去(PS:越来越懒了). 一.Thread 利用Thread 可以直接创建和控制线程,在我的认知里它是最古老的技术了 ...

  4. Java通过JDBC连接数据库的三种方式!!!并对数据库实现增删改查

    前言 java连接数据库完整流程为: 1,获得驱动(driver),数据库连接(url),用户名(username),密码(password)基本信息的三种方式. 2,通过获得的信息完成JDBC实现连 ...

  5. String常用使用方法,1.创建string的常用3+1种方式,2.引用类型使用==比较地址值,3.String当中获取相关的常用方法,4.字符串的截取方法,5.String转换常用方法,6.切割字符串----java

    一个知识点使用一个代码块方便查看 1.创建string的常用3+1种方式 /* 创建string的常用3+1种方式 三种构造方法 public String():创建一个空字符串,不含有任何内容: p ...

  6. ios多线程开发的常用三种方式

    1.NSThread 2.NSOperationQueue 3.GCD NSThread: 创建方式主要有两种: [NSThread detachNewThreadSelector:@selector ...

  7. HBase读写的几种方式(三)flink篇

    1. HBase连接的方式概况 主要分为: 纯Java API读写HBase的方式: Spark读写HBase的方式: Flink读写HBase的方式: HBase通过Phoenix读写的方式: 第一 ...

  8. 创建线程的三种方式(Thread、Runnable、Callable)

    方式一:继承Thread类实现多线程: 1. 在Java中负责实现线程功能的类是java.lang.Thread 类. 2. 可以通过创建 Thread的实例来创建新的线程. 3. 每个线程都是通过某 ...

  9. 多线程,线程类三种方式,线程调度,线程同步,死锁,线程间的通信,阻塞队列,wait和sleep区别?

    重难点梳理 知识点梳理 学习目标 1.能够知道什么是进程什么是线程(进程和线程的概述,多进程和多线程的意义) 2.能够掌握线程常见API的使用 3.能够理解什么是线程安全问题 4.能够知道什么是锁 5 ...

随机推荐

  1. css3圆形百分比进度条的实现原理

    原文地址:css3圆形百分比进度条的实现原理 今天早上起来在查看jquery插件机制的时候,一不小心点进了css3圆形百分比进度条的相关文章,于是一发不可收拾,开始折腾了... 关于圆形圈的实现,想必 ...

  2. 微信小程序教程汇总

    目前市面上在内测期间出来的一些实战类教程还是很不错的,主要还是去快速学习小程序开发的整体流程,一个组件一个组件的讲的很可能微信小程序一升级,这个组件就变了,事实本就如此,谁让现在是内测呢.我们不怕,下 ...

  3. css3制作旋转动画

    现在的css3真是强大,之前很多动画都是用jq来实现,但是css3制作的动画要比jq实现起来简单很多,今天呢,我自己也写了一个css旋转动画和大家分享.效果如下面的图片 思路:1.制作之前呢,我们先来 ...

  4. SQL-union

    集合运算符是对两个集合操作的,两个集合必须具有相同的列数,列具有相同的数据类型(至少能隐式转换的),最终输出的集合的列名由第一个集合的列名来确定.(可以用来连接多个结果)联合(union)与连接(jo ...

  5. ASP.NET Core 中间件详解及项目实战

    前言 在上篇文章主要介绍了DotNetCore项目状况,本篇文章是我们在开发自己的项目中实际使用的,比较贴合实际应用,算是对中间件的一个深入使用了,不是简单的Hello World,如果你觉得本篇文章 ...

  6. ASP.NET Aries JSAPI 文档说明:AR.Form、AR.Combobox

    AR.Form 文档 1:对象或属性: 名称 类型 说明 data 属性 编辑页根据主键请求回来的数据 method 属性 用于获取数据的函数指向,默认值Get objName 属性 用于拦截form ...

  7. FastClick 填坑及源码解析

    最近产品妹子提出了一个体验issue —— 用 iOS 在手Q阅读书友交流区发表书评时,光标点击总是不好定位到正确的位置: 如上图,具体表现是较快点击时,光标总会跳到 textarea 内容的尾部.只 ...

  8. .NET Web的身份认证

    百度一下”asp.net身份认证“,你会得到很多相关的资料,这些资料通常上来就会介绍诸如”Form认证“”Windows认证“等内容,而没有给出一个完整的流程.初学者对此往往一头雾水,我也曾经被坑过很 ...

  9. 完善Person页面的视图操作功能

    经过上一篇,我们的person的权限已经正常加上了.那么我们回到我们的菜单类.给他重新加上权限. 这样的话,我们在启动页面的时候就不会看见联系人管理菜单了.只有登录后才可以看到菜单信息了. 添加控制器 ...

  10. BVT & BAT (版本验证测试和版本验收测试)

    BVT & BAT 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.BVT: (Build Verification Test ) BVT的概念: BVT(版本验证测试)是在所有开发 ...