简介
  在C#中实现多线程的另一个方式是使用Parallel类。
  在.NET4中 ,另一个新增的抽象线程是Parallel类 。这个类定义了并行的for和foreach的 静态方法。在为 for和 foreach定 义的语言中,循环从一个线程中运行 。Parallel类使用多个任务,因此使用多个线程来完成这个作业。
  我们在前文中,对任务作出了一定的阐释,有兴趣的朋友可以前去查看。
  Parallel.For()和 Parallel.ForEach()方法多次调用同一个方法,而 Parallel.Invoke()方法允许同时调用不同的方法。

使用Parallel.For()方法
  基本使用方法
  Parallel.For()方法类似于 C#的 for循环语旬,也是多次执行一个任务。使用Parallel.For()方法,可以并行运行迭代。 迭代的顺序没有定义。
  在For()方法中,前两个参数定义了循环的开头和结束。示例从0迭代到 9。第 3个参数是一个Action<int>委托。 整数参数是循环的迭代次数,该 参数被传递给Action<int>委托引用的方法。Parallel.For()方法的返回类型是ParalleLoopResult结构,它提供了循环是否结束的信息。

ParallelLoopResult result = Parallel.For(0, 10, i =>
{
Console.WriteLine("{0}, task : {1}, thread : {2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine(result.IsCompleted);
Console.ReadKey();
1
2
3
4
5
6
  在Parallel.For()的方法体中,把索引、任务标识符和线程标识符写入控制台中。从下面的输出截图可以看出,由于每次循环都开启了新的任务和线程,因此每个线程的执行顺序是不能保证的。
  

  中断循环
  同For()循环类似,Parallel.For()方法也可以中断循环的执行。
  Parallel.For()方法的一个重载版本接受第3个Action<int, ParallelLoopState>类型的参数。使用这些参数定义一个方法,就可以调用ParalleLoopState的Break()或Stop()方法,以影响循环的结果。
  注意,迭代的顺序没有定义。

ParallelLoopResult result = Parallel.For(0, 10, (int i, ParallelLoopState pls) =>
{
Console.WriteLine("i: {0}, task : {1}", i, Task.CurrentId);
Thread.Sleep(10);
if (i > 15)
{
pls.Break();
}
});
Console.WriteLine(result.IsCompleted);
Console.WriteLine("Lowest break iteration: {0}", result.LowestBreakIteration);
Console.ReadKey();
1
2
3
4
5
6
7
8
9
10
11
12
  下面是结果截图:
  
  
  应用程序这次的运行说明,迭代在值大于15时中断,但其他任务可以同时运行,有其他值的任务也可以运行。利用LowestBreakIteration属性,可以忽略其他任务的结果。

  Parallel.For<TLocal>方法
  Parallel.For()方法可能使用几个线程来执行循环 。如果需要对每个线程进行初始化,就可以使用Parallel.For<TLocal>方法。除了from和to对应的值之外,For()方法的泛型版本还接受3个委托参数。
  第一个参数的类型是Func<TLocal> ,因为这里的例子对于TLocal使用字符串,所以该方法需要定义为Func<string>,即返回string的方法。这个方法仅对于用于执行迭代的每个线程调用一次。
  第二个委托参数为循环体定义了委托。在示例中,该参数的类型是Func<int, ParallelLoopState, string, string>。 其中第一个参数是循环迭代,第二个参数 ParallelLoopstate允许停止循环,如前所述 。循环体方法通过第3个参数接收从init方法返回的值,循环体方法还需要返回一个值,其类型是用泛型for参数定义的。
  For()方法的最后一个参数指定一个委托Action<TLocal>;在该示例中,接收一个字符串。 这个方法仅对于每个线程调用一次,这是一个线程退出方法。

Parallel.For<string>(0, 20,
() =>
{
Console.WriteLine("init thread {0},\t task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
return string.Format("t{0}", Thread.CurrentThread.ManagedThreadId);
},
(i, pls, str) =>
{
Console.WriteLine("body i {0} \t str {1} \t thread {2} \t task {3}", i, str, Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
Thread.Sleep(10);
return string.Format("i \t{0}", i);
},
(str) =>
{
Console.WriteLine("finally\t {0}", str);
});
Console.ReadKey();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  程序运行结果:

  备注:
  Parallel.For<TLocal> 方法 (Int32, Int32, Func<TLocal>, Func<Int32, ParallelLoopState, TLocal, TLocal>, Action<TLocal>)
  类型参数
  TLoca
  线程本地数据的类型。

  参数

  fromInclusive
  类型:System.Int32
  开始索引(含)。

  toExclusive
  类型:System.Int32
  结束索引(不含)。

  localInit
  类型:System.Func<TLocal>
  用于返回每个任务的本地数据的初始状态的函数委托。

  body
  类型:System.Func<Int32, ParallelLoopState, TLocal, TLocal>
  将为每个迭代调用一次的委托。

  localFinally
  类型:System.Action<TLocal>
  用于对每个任务的本地状态执行一个最终操作的委托。

  返回值
  类型:System.Threading.Tasks.ParallelLoopResult
  
  在迭代范围 (fromInclusive,toExclusive) ,为每个值调用一次body 委托。为它提供以下参数:迭代次数 (Int32)、可用来提前退出循环的ParallelLoopState实例以及可以在同一线程上执行的迭代之间共享的某些本地状态。

  对于参与循环执行的每个任务调用 localInit 委托一次,并返回每个任务的初始本地状态。 这些初始状态传递给第一个在该任务上 调用的 body。 然后,每个后续正文调用返回可能修改过的状态值,传递到下一个正文调用。 最后,每个任务上的最后正文调用返回传递给 localFinally 委托的状态值。 每个任务调用 localFinally 委托一次,以对每个任务的本地状态执行最终操作。此委托可以被多个任务同步调用;因此您必须同步对任何共享变量的访问。

  Parallel.For方法比在它执行生存期的线程可能使用更多任务,作为现有的任务完成并被新任务替换。 这使基础 TaskScheduler 对象有机会添加、更改或移除服务循环的线程。

  如果 fromInclusive 大于或等于 toExclusive,则该方法立即返回,而无需执行任何迭代。

使用Parallel.ForEach()方法
  基本使用方法
  Parallel.ForEach()方法遍历实现了IEnumerable的集合,其方式类似于foreach语句,但以异步方式遍历。这里也没有确定遍历顺序。
  

string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve" };
ParallelLoopResult result = Parallel.ForEach<string>(data, (s) =>
{
Console.WriteLine(s);
});
Console.ReadKey();
1
2
3
4
5
6
  结果截图:

  中断循环
  如果需要中断循环,就可以使用ForEach()方法的重载版本和ParallelLoopState参数。其方式与前面的For()方法相同。ForEach()方法的一个重载版本也可以用于访问索引器,从而获得迭代次数,如下所示: 

string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve" };
ParallelLoopResult result = Parallel.ForEach<string>(data, (s, pls, l) =>
{
Console.WriteLine("{0}\t{1}", s, l);
if (l > 10)
{
pls.Break();
}
});
Console.WriteLine("Lowest break iteration: {0}", result.LowestBreakIteration);
Console.ReadKey();
1
2
3
4
5
6
7
8
9
10
11
  结果截图:

使用Parallel.Invoke()方法
  如果多个任务应并行运行,就可以使用Parallel.Invoke()方法。Parallel.Invoke()方法允许传递一个Action委托数组,在其中可以指定应运行的方法。
  示例代码传递了要并行调用的Foo()和Bar()方法:
  

static void Main(string[] args)
{
Parallel.Invoke(Foo, Bar);
Console.ReadKey();
}
static void Foo()
{
Console.WriteLine("Foo");
}

static void Bar()
{
Console.WriteLine("Bar");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  结果截图:
  
---------------------
作者:诗人江湖老
来源:CSDN
原文:https://blog.csdn.net/honantic/article/details/46876871
版权声明:本文为博主原创文章,转载请附上博文链接!

转载 [深入学习C#]C#实现多线程的方式:使用Parallel类的更多相关文章

  1. [深入学习C#]C#实现多线程的方式:使用Parallel类

    简介 在C#中实现多线程的另一个方式是使用Parallel类.  在.NET4中 ,另一个新增的抽象线程是Parallel类 .这个类定义了并行的for和foreach的 静态方法.在为 for和 f ...

  2. [深入学习C#]C#实现多线程的方式:Task——任务

    简介 .NET 4包含新名称空间System.Threading.Tasks,它 包含的类抽象出了线程功能. 在后台使用ThreadPool. 任务表示应完成的某个单元的工作. 这个单元的工作可以在单 ...

  3. 转:学习笔记:delphi多线程学识

    学习笔记:delphi多线程知识 最近一直在温习旧的知识,刚好学习了一下Java的线程安全方面的知识,今天想起之前一直做的Delphi开发,所以还是有必要温习一下,看看这些不同的编程语言有什么不同之处 ...

  4. 【转载】.NET Remoting学习笔记(二)激活方式

    目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 参考:百度百科 ♂风车车.Net 激活方式概念 在访 ...

  5. 学习笔记《Java多线程编程实战指南》二

    2.1线程属性 属性 属性类型及用途  只读属性  注意事项 编号(id) long型,标识不同线程  是  不适合用作唯一标识 名称(name) String型,区分不同线程  否  设置名称有助于 ...

  6. Java学习个人备忘录之多线程

    进程:正在进行中的程序(直译). 线程:就是进程中一个负责程序执行的控制单元(执行路径) 一个进程中可以有多个执行路径,称之为多线程. 一个进程中至少要有一个线程. 开启多个线程是为了同时运行多部分代 ...

  7. 【ALB学习笔记】基于多线程方式的串行通信接口数据接收案例

    基于多线程方式的串行通信接口数据接收案例 广东职业技术技术学院  欧浩源 1.案例背景 在本博客的<[CC2530入门教程-06]CC2530的ADC工作原理与应用>中实现了电压数据采集的 ...

  8. .NET Remoting学习笔记(二)激活方式

    目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 参考:百度百科  ♂风车车.Net 激活方式概念 在 ...

  9. 夯实Java基础系列17:一文搞懂Java多线程使用方式、实现原理以及常见面试题

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

随机推荐

  1. 关于 RESTFUL API 安全认证方式的一些总结

    常用认证方式 在之前的文章REST API 安全设计指南与使用 AngularJS & NodeJS 实现基于 token 的认证应用两篇文章中,[译]web权限验证方法说明中也详细介绍,一般 ...

  2. JavaSE Lambda表达式(JDK1.8新特性)

    在前面有一篇写到了Lambda表达式,现在可以给你们介绍什么是Lambda表达式 现在有很多老程序员都不喜欢这个函数式编程思想 主要就一点 : 老程序员习惯了 面向过程 写程序,而Lambda表达式是 ...

  3. Django Rest framework 之 解析器

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

  4. Vue遇到的一些小坑

    1.在使用v-html指令时,发现添加的元素不能设置样式 解决方案:在添加样式时使用>>>就可以添加成功 例如:<div v-html="<img src=&q ...

  5. NODE获取节点删除空格的操作

    NODE节点操作有: object.parentNode:获取某子元素的父级: object.childNodes:是获取所有的子元素节点,返回数组类型: object.lastChild: 获取该元 ...

  6. 使用node.js进行API自动化回归测试

    概述 传统的QA自动化测试通常是基于GUI的,比如使用Selenium,模拟用户在界面上操作.但GUI测试的开发.维护成本和运行的稳定性一直是测试界的老大难问题.投入大量的人力物力开发.维护.运行,却 ...

  7. Flutter 不一样的跨平台解决方案

    本文主要介绍Flutter相关的东西,包括Fuchsia.Dart.Flutter特性.安装以及整体架构等内容. 1. 简介 Flutter作为谷歌最近推出的跨平台开发框架,一经推出便吸引了不少注意. ...

  8. (后台)El表达式格式化两位小数

    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>引入标签库. < ...

  9. dmesg七种用法

    dmesg 命令的使用范例 ‘dmesg’命令设备故障的诊断是非常重要的.在‘dmesg’命令的帮助下进行硬件的连接或断开连接操作时,我们可以看到硬件的检测或者断开连接的信息.‘dmesg’命令在多数 ...

  10. 洗礼灵魂,修炼python(10)--有趣的判断分支+从实例中掌握循环语句

    所有的编程语言里都有判断语句和循环语句. 判断语句则是用来分支程序流程的 循环语句则是为了实现一个效果,让程序的规律性的重复操作 不用说,分支和循环自然在python里也是有的 一,条件判断:if,i ...