C#实现多线程的方式:使用Parallel类
简介
在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(, , i =>
{
Console.WriteLine("{0}, task : {1}, thread : {2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine(result.IsCompleted);
Console.ReadKey();
在Parallel.For()的方法体中,把索引、任务标识符和线程标识符写入控制台中。从下面的输出截图可以看出,由于每次循环都开启了新的任务和线程,因此每个线程的执行顺序是不能保证的。
中断循环
同For()循环类似,Parallel.For()方法也可以中断循环的执行。
Parallel.For()方法的一个重载版本接受第3个Action<int, ParallelLoopState>类型的参数。使用这些参数定义一个方法,就可以调用ParalleLoopState的Break()或Stop()方法,以影响循环的结果。
注意,迭代的顺序没有定义。
ParallelLoopResult result = Parallel.For(, , (int i, ParallelLoopState pls) =>
{
Console.WriteLine("i: {0}, task : {1}", i, Task.CurrentId);
Thread.Sleep();
if (i > )
{
pls.Break();
}
});
Console.WriteLine(result.IsCompleted);
Console.WriteLine("Lowest break iteration: {0}", result.LowestBreakIteration);
Console.ReadKey();
下面是结果截图:
应用程序这次的运行说明,迭代在值大于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>(, ,
() =>
{
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();
return string.Format("i \t{0}", i);
},
(str) =>
{
Console.WriteLine("finally\t {0}", str);
});
Console.ReadKey();
程序运行结果:
备注:
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();
结果截图:
中断循环
如果需要中断循环,就可以使用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 > )
{
pls.Break();
}
});
Console.WriteLine("Lowest break iteration: {0}", result.LowestBreakIteration);
Console.ReadKey();
结果截图:
使用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");
}
结果截图:
转载来源
http://blog.csdn.net/honantic/article/details/46876871
C#实现多线程的方式:使用Parallel类的更多相关文章
- 转载 [深入学习C#]C#实现多线程的方式:使用Parallel类
简介 在C#中实现多线程的另一个方式是使用Parallel类. 在.NET4中 ,另一个新增的抽象线程是Parallel类 .这个类定义了并行的for和foreach的 静态方法.在为 for和 fo ...
- 【.Net】C#实现多线程的方式:使用Parallel类
简介 在C#中实现多线程的另一个方式是使用Parallel类. 在.NET4中 ,另一个新增的抽象线程是Parallel类 .这个类定义了并行的for和foreach的 静态方法.在为 for和 f ...
- [深入学习C#]C#实现多线程的方式:使用Parallel类
简介 在C#中实现多线程的另一个方式是使用Parallel类. 在.NET4中 ,另一个新增的抽象线程是Parallel类 .这个类定义了并行的for和foreach的 静态方法.在为 for和 f ...
- 数据与任务的并行---Parallel类
Parallel类是对线程的抽象,提供数据与任务的并行性.类定义了静态方法For和ForEach,使用多个任务来完成多个作业.Parallel.For和Parallel.ForEach方法在每次迭代的 ...
- 一、并行编程 - 数据并行 System.Threading.Tasks.Parallel 类
一.并行概念 1.并行编程 在.NET 4中的并行编程是依赖Task Parallel Library(后面简称为TPL) 实现的.在TPL中,最基本的执行单元是task(中文可以理解为"任 ...
- java中创建多线程的方式
在java中比较常用的有三种创建多线程的方式. 方式一:继承Thread类,要重写run方法. 在MyThread类 public class MyThread extends Thread { @O ...
- 多线程之Parallel类
Parallel类是对线程的一个抽象.该类位于System.Threading.Tasks名称空间中,提供了数据和任务并行性. Paraller类定义了数据并行地For和ForEach的静态方法,以及 ...
- C# 并行任务——Parallel类
一.Parallel类 Parallel类提供了数据和任务的并行性: 二.Paraller.For() Paraller.For()方法类似于C#的for循环语句,也是多次执行一个任务.使用Paral ...
- 第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)
一. 并行编程 1. 区分串行编程和串行编程 ①. 串行编程:所谓的串行编程就是单线程的作用下,按顺序执行.(典型代表for循环 下面例子从1-100按顺序执行) ②. 并行编程:充分利用多核cpu的 ...
随机推荐
- 用go iris 写的一个网页版文件共享应用(webapp)
主要演示文件拖拽上传或点击上传到不同的目录中,提供下载和删除功能. 目录结构: -main.go --share(用于分类存放上传文件的目录) --v(视图目录) ---share.html main ...
- 【原创】Python3 + Red + PyDev + Eclipse + Subversion + RobotFramework + UI Automator2 + Weditor 构建Web+Mobile 交互式移动App自动化测试环境
环境搭建步骤: 1. 下载安装Oracle JDK: 安装路径设置为C:\Program Files\Java\jdk1.8.0_152 2. 下载安装Eclipse: 安装路径设置为C:\Eclip ...
- 错误/异常:org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save() 的解决方法
1.错误/异常视图 错误/异常描述:id的生成错误,在调用save()方法之前,必须先生成id. 2.解决方法 在对应的实体类的主键(id)的get方法上加上:@GeneratedValue( ...
- Comet OJ - Contest #3 D 可爱的菜菜子 线段树+线性基
题意 给你一个长度为 \(n\) 的整数序列 \(a_1, a_2, \ldots, a_n\),你需要实现以下两种操作,每个操作都可以用四个整数 \(opt\ l\ r\ v\) 来表示: \(op ...
- Linux Shell脚本,删除旧文件,保留最新的几个文件
删除某一目录下文件,只保留最新的几个 #!/bin/bash #保留文件数 ReservedNum= FileDir=/home/dev/saas_test/testcases/report/html ...
- BZOJ1706奶牛接力跑
这个东西思路还是不错的. 解法就是把矩阵幂的加法改成取min,乘法改成加法就好,和floyed是一样的.这样的话,矩阵操作一次就相当于松弛了一次最短路. 建矩阵的过程也比较简单,可以离散化,当然下面有 ...
- 两次取反 !!a 的作用
两次取反的作用 让a的结果只能是false或者是true:如果a是0:两次取反当然是false:如果a是null:两次取反是false:如果a是undefined:两次取法是false:其余的比如 a ...
- centos6一键安装WordPress
#!/bin/bash service iptables stop setenforce yum -y install httpd service httpd restart yum -y insta ...
- Workflow-产品:泛微工作流引擎
ylbtech-Workflow-产品:泛微工作流引擎 1.返回顶部 1. 工作流引擎平台技术架构 TECHNOLOGY FRAMEWORK 高度协同系统各应用模块 泛微工作流引擎平台是整个协同办公平 ...
- Alert 警告
基本用法 页面中的非浮层元素,不会自动消失. Alert 组件提供四种主题,由type属性指定,默认值为info. <template> <el-alert title=" ...