.Net并行编程高级教程(二)-- 任务并行
2015-10-29 08:28
330 查看
前面一篇提到例子都是数据并行,但这并不是并行化的唯一形式,在.Net4之前,必须要创建多个线程或者线程池来利用多核技术。现在只需要使用新的Task实例就可以通过更简单的代码解决命令式任务并行问题。
1.Task及它的生命周期
一个Task表示一个异步操作,它的创建和执行都是独立的,因此可以对相关操作的执行拥有完全的控制权;当有很多异步操作作为Task实例加载的时候,为了充分利用运行时的逻辑内核,任务调度器会尝试并行的运行这些任务,当然任务都是有额外的开销,虽然要小于添加线程的开销;
对Task实例的生命周期的理解非常重要。一个Task的执行,取决于底层硬件和运行时可用的资源。因此Task实例的状态会不断的发生改变,而一个Task实例只会完成其生命周期一次,当Task到达它三种可能的最终状态只后,它就回不去之前的任何状态了。
View Code
而这时的StartNew创建的类型是Task<List<String>>.StartNew源码如下:
我们还可以将任务串联起来。比如上面的代码。避免写太多代码来检查前面一个任务是否完成。而ContinueWith这个方法可以用来串联多个任务。
如果需要设置继续的条件,就要用到TaskContinuationOptions,它是一个枚举类型,用来控制另一个任务执行和调度的可选行为
NotOnCanceled,就是表示上个任务不取消的情况下执行。例如还有NotOnFaulted.如果上一个任务抛出了异常,那么就不会执行。这里就不一一例举了。
小结:这一章主要是将了基于任务的编程模型,学习了任务的创建、状态,以及如何取消、捕获异常和获得返回值,并能串行任务,任务的延续不仅能简化代码,而且还能帮助调度器对很快就要执行的任务采取正确的操作。下一章学习并发集合。
http://www.cnblogs.com/stoneniqiu/p/4873544.html
1.Task及它的生命周期
一个Task表示一个异步操作,它的创建和执行都是独立的,因此可以对相关操作的执行拥有完全的控制权;当有很多异步操作作为Task实例加载的时候,为了充分利用运行时的逻辑内核,任务调度器会尝试并行的运行这些任务,当然任务都是有额外的开销,虽然要小于添加线程的开销;
对Task实例的生命周期的理解非常重要。一个Task的执行,取决于底层硬件和运行时可用的资源。因此Task实例的状态会不断的发生改变,而一个Task实例只会完成其生命周期一次,当Task到达它三种可能的最终状态只后,它就回不去之前的任何状态了。
private static List<string> GenerateMD5HasList(CancellationToken ct, char prefix) { ct.ThrowIfCancellationRequested(); var sw = Stopwatch.StartNew(); var list = new List<string>(); for (int i = 0; i < NUM_AES_KEYS; i++) { var md5M = MD5.Create(); byte[] data = Encoding.Unicode.GetBytes(Environment.UserName + i); byte[] result = md5M.ComputeHash(data); string hexString = ConverToHexString(result); if (hexString[0] == prefix) { list.Add(hexString); } ct.ThrowIfCancellationRequested(); } Console.WriteLine("MD5:" + sw.Elapsed); return list; }
View Code
Console.WriteLine("任务开始..."); var cts = new CancellationTokenSource(); var ct = cts.Token; var t1 = Task.Factory.StartNew(() => GenerateMD5HasList(ct,'A'), ct); //等待执行完成 t1.Wait(); var res = t1.Result; for (int i = 0; i < res.Count; i++) { Console.WriteLine(res[i]); }
而这时的StartNew创建的类型是Task<List<String>>.StartNew源码如下:
public Task<TResult> StartNew<TResult>(Func<TResult> function) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; Task currTask = Task.InternalCurrent; return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken, m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark); }
我们还可以将任务串联起来。比如上面的代码。避免写太多代码来检查前面一个任务是否完成。而ContinueWith这个方法可以用来串联多个任务。
var t1 = Task.Factory.StartNew(() => GenerateMD5HasList(ct,'A'), ct); var t2 = t1.ContinueWith((t) => { for (int i = 0; i < t.Result.Count; i++) { Console.WriteLine(t.Result[i]); } }); //可以等待t2执行完成 t2.Wait();
如果需要设置继续的条件,就要用到TaskContinuationOptions,它是一个枚举类型,用来控制另一个任务执行和调度的可选行为
var t2 = t1.ContinueWith((t) => OtherMethod(t), TaskContinuationOptions.NotOnCanceled);
NotOnCanceled,就是表示上个任务不取消的情况下执行。例如还有NotOnFaulted.如果上一个任务抛出了异常,那么就不会执行。这里就不一一例举了。
小结:这一章主要是将了基于任务的编程模型,学习了任务的创建、状态,以及如何取消、捕获异常和获得返回值,并能串行任务,任务的延续不仅能简化代码,而且还能帮助调度器对很快就要执行的任务采取正确的操作。下一章学习并发集合。
http://www.cnblogs.com/stoneniqiu/p/4873544.html
相关文章推荐
- 【C/C++学院】0822-类型转换函数与构造转换函数/类的继承/类的继承以及区别/继承静态成员与静态函数//继承实现代码重用/单继承QT案例/多继承简介以及实战/Gpu编程
- java 不可变类 缓存实例
- java 实现WebService 以及不同的调用方式
- Java 复制文件的高效方法
- 消除C++中警告代码
- 挑战这十七项编程 锻炼大脑并且提升能力
- Kd-Tree算法原理和开源实现代码
- CryEngine3渲染引擎剖析
- 不疯魔,不成活,Rackspace为什么对管理云如此狂热
- 在C语言中函数中使用枚举类型和结构
- spring的IOC与AOP读源码小记
- 关于为什么java中public修饰的类的类名和文件名要一致的个人看法
- php面向对象(一)
- java_class.getMethod 与 class.getDeclaredMethod的区别
- c语言编程的乘法口诀表
- spring 与设计模式(创建型)之单例Singleton
- 用C语言输出一个菱形
- 猜数字游戏
- C++:IO缓冲区
- 编程笑脸迷宫