




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
NET4 0 并行计算技术基础 8 有些朋友来邮件询问本系列文章的示例源码 由于我没有发现 CSDN 博客直接提供了上传 附件的功能 所以打算等本章所有文章贴完以后 再将所有源码打包上传到 CSDN 下载频 道 另外 要想看懂本系列文章 需要您对 NET 多线程开发有基本的了解 我在新书中花了 近 200 页的篇幅来介绍 NET 多线程开发技术 可帮助大家循序渐进地掌握技术 呵呵 在此先作个广告 今天贴出第 8 讲 任务的同步 本章内容过半了 金旭亮 2009 10 12 19 3 6 同步多个任务同步多个任务 在并行计算应用程序中 通常会创建多个 Task 对象以执行不同的工作任务 而依据具体应用场景 这些工作任务对象之间又会有着相互协作的需求 比如 可能要求某个工作任务完成以后自动启动一个或多个新的 Task 对象执行后继 处理工作 或者某个正在执行的工作任务中途需要等待另一个工作任务执行完 毕才能执行 这就是任务的同步问题 Task 类提供了 ContinueWith 和 Wait 系列方法 在 任务 的层次 而 不是线程的层次 实现任务的同步 1 使用使用 ContinueWith 例如 以下代码在 task1 完成之后自动运行 task2 Task task1 new Task DoStep1 Task task2 task1 ContinueWith PrevTask DoStep2 task1 Start 上述代码中的 PrevTask 参数代表已完成的 前辈 Task 对象 TPL 会 将此对象传给后继的 Task 对象 因此 在后继对象中可以通过此参数获取前 一个任务的相关信息 ContinueWith 方法有多个重载形式 其中很有用的是返回一个 Task 的重载形式 public Task ContinueWith Func Task Task continuationFunction 当任务需要返回一个唯一值时 可以使用这个重载形式 有的 ContinueWith 方法重载形式接收一个 TaskContinuationOptions 类型 的参数 public Task ContinueWith Action continuationAction TaskContinuationOptions continuationOptions TaskContinuationOptions 是一个枚举 可以使用它来指定 在何种情况下 才执行后继的工作任务 例如 以下代码指定只有 task1 中有未捕获的异常时 才运行 task2 Task task2 task1 ContinueWith PrevTask DoWithException TaskContinuationOptions OnlyOnFaulted 2 使用使用 Wait 系列方法系列方法 另一个被广泛使用的任务同步手段是 Task 类的 Wait 系列方法 此系列方 法可分为 3 类 每类方法又有着多个重载形式 1 Wait 等待单个任务的完成 2 WaitAll 等待一组任务的全部完成 3 WaitAny 等待一组任务的任何一个任务完成 当并行程序调用上述方法时 会在调用线程上阻塞等待任务完成 以下代码等待单个任务的完成 Task t Task Create t Wait 以下代码等待多个任务的完成 Task t1 Task Create Task t2 Task Create Task t3 Task Create Task WaitAll t1 t2 t3 将上述代码中的 WaitAll 改为 WaitAny 则 t1 t2 t3 中任何一个完成时 当前任务都会结束等待状态而继续执行 3 创建父子类型的任务创建父子类型的任务 当一个任务会创建另一个任务时 称此任务为 父任务 被创建的为 子任务 使用任务之间的 父子关系 可以实现类似于 Task ContinueWith 的功能 Task tskParent new Task 父任务完成的工作 创建后继子任务并自动启动 Task Factory StartNew MethodA Task Factory StartNew MethodB Task Factory StartNew MethodC 启动父任务 tskParent Start 等待整个任务的完成 tskParent Wait 与使用 Task ContinueWith 相比 使用父子任务的好处在于可以减少应用程 序需要跟踪状态的任务对象个数 4 非阻塞方式等待非阻塞方式等待 不管是使用 ContinueWith 还是 Wait 系列方法 调用这些方法的线程都会 阻塞等待 如果不希望阻塞当前线程 可以通过轮询 Task 对象的 IsCompleted 属性来了解其是否完成 以下是框架代码 while task1 IsCompleted Thread SpinWait 10000000 让当前线程时刻盯着前 一任务的完成状态 可以安排进行其它工作 task1 已完成 进行后继工作 5 小结小结 本节介绍的任务同步的方法都很简单 但通过灵活的组合 可以实现复杂的并行计算 任务 而同样的功能 如果直接使用线程来处理 其工作量会增加很多 这也是使用任务 并行库优越性的表现之一 19 3 7 任务处理结果的取回任务处理结果的取回 任何一个并行计算程序都需要处理一定量的数据 因此 需要解决如何将 数据在任务中传送并在合适的时候取回处理结果的问题 1 使用线程同步手段取回数据处理结果使用线程同步手段取回数据处理结果 我们使用 Task 对象来代表一个并行处理任务 并调用其 Start 方法启动 并行处理过程 从 Task 类的构造函数可以看到 每个 Task 类关联的是一个 Action 或 Action 委托 其所引用的函数其返回值为 void 很明显此函数 无法直接将处理结果返回给任务的启动者 然而 由于任务的执行是由线程负责的 所以 可以在任务函数中直接访 问程序中的用于保存处理结果的共享资源 比如某个对象的公有属性 或者类 的静态成员等 但这时 必须使用一种线程同步手段来通知任务启动者线程 本线程工作结束 从而启动任务的线程可以从共享资源中取回处理结果 请看示例程序 GetResultFromTask 这个程序在内部使用了一个 ManualResetEvent 对象 主线程在启动处理工作后等待此对象变为 Signaled 状 态 示例程序通过 Task 对象启动一个数组求和计算任务 在其任务函数中将 处理结果保存到一个共享的静态字段中 然后 ManualResetEvent Set 方法通 知主线程可以取出处理结果 这种方法虽然可行 但本质上还是基于 线程 的开发 TPL 的优势没有 显示出来 2 使用使用 TPL 提供的任务同步手段取回处理结果提供的任务同步手段取回处理结果 我们完全可以不用 原始 的线程同步对象 而直接使用 TPL 所提供的任 务同步机制达到同样的目的 请看示例项目 GetResultFromTaskWithoutThreadSync 它与前一个示例项 目 GetResultFromTask 功能完成一样 但它利用到了 Task 对象的 ContinueWith 方法 public Task ContinueWith Action continuationAction 注意这是一个实例方法 对它的调用将返回一个新的 Task 对象 这个对象 引用的任务函数由方法参数提供 这一方法的功能是 当前 Task 对象的任务函数执行完毕后 自动启动其 ContinueWith 方法 所创建的 后继 Task 对象 当前 已完成 的 Task 对象将作为 后继 Task 对象任务函数的参数传入 下面列出示例的代码框架 详细代码请直接看项目源码 static void Main string args 需要并行执行的数据处理函数 Action ProcessData delegate object end 编写代码完成数据处理工作 保存处理结果 用于取回处理结果的函数 Action GetResult delegate Task finishedTask if finishedTask IsFaulted Console WriteLine 任务在执行时发生异常 finishedTask Exception Message else Console Write 程序运行结果为 0 Program result 创建并行处理数据的任务对象 Task tskProcess new Task ProcessData 1000000 当数据处理结束时 自动启动下一个工作任务 取回上一任务的处 理结果 Task tskGetResult tskProcess ContinueWith GetResult 开始并行处理数据 tskProcess Start Console ReadKey 上述代码非常简明 值得注意的是在后继的任务中可以通过检测 已完成 的 Task 对象的 IsFaulted 属性得知是否在其处理过程出现了异常 通过连续使用 ContinueWith 方法 我们可以启动一连串的 首尾 相接 的任务 因此特别适合并行执行多个任务 每个任务内部又包容着一系列需要 顺序执行的子任务 有关任务之间相互协作与配合 称为 任务同步 的问题 后面章节中 还有介绍 3 使用使用 Task 得到任务处理结果得到任务处理结果 与 Task 不一样 Task 类直接关联一个可以有返回值的函数 以 下是它的一个构造函数 public Task Func function object state 从这个构造函数可以看出 Task 对象关联着一个任务函数 由 function 参数引用此函数 构造函数中的 object 参数将成为任务函数的实参 Task 类提供了一个 Result 属性用于取回任务函数的执行结果 public TResult Result get internal set 可以直接使用 new 关键字创建 Task 类的实例 然后手动调用其 Start 方法启动 也可以通过工厂类 TaskFactory 的 StartNew 方法 一步完成创建任务对象和启动运行的工作 Task 类提供了以下静态 属性引用工厂类 public static TaskFactory Factory get 示例程序 GetResultFromTaskTResult 展示了 Task 类的用法 其代 码框架如下 static void Main string args 完成数据处理工作 结果将作为函数返回值 Func del delegate object end long result 0 数据处理代码略 return result Task tsk new Task del 1000000 启动运行 tsk Start 取回结果 Console Write 程序运行结果为 0 tsk Result Console ReadKey 这里比较有趣的是整个代码中没有一句线程同步代码 您可能会奇怪 主 线程与工作线程的同步是怎么实现的 主线程如何知道工作线程承担的工作任 务已处理结束 答案就在 Task 类的 Result 属性中 请注意 Task 类 派生自 Task 类 而此 Task 类提供了一个 Wait 方法用于等待工作任务的执 行结束 所以 在访问 Task 类的 Result 属性时 如果工作任务还未 执行完毕 则尝试取回结果的线程会阻塞等待 因为 Result 属性的 get 访问 器函数一直没有返回 请看以下框架代码 public TResult Result get if base IsCompleted base Wait 阻塞等待任务的执行结束 internal set 上述代码另一个要注意的地方是 R
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 安全无毒消杀培训内容课件
- 生产安全单位安全培训课件
- 农业碳汇项目碳排放监测与减排效果评估报告
- 理财课程解读课件
- 改造工程标段划分方案(3篇)
- 饭堂净水工程方案(3篇)
- 顶管工程测量方案(3篇)
- 安全文明施工内容培训课件
- 猫郑振铎课件简介
- 分包工程接口方案(3篇)
- 肿瘤放疗并发症综合防治
- 口腔医疗风险管理实施方案
- 2024年中国中间相沥青行业调查报告
- 毒蕈中毒健康教育课件
- DRG视角下护理管理
- 水电厂自动化管理制度
- 2025-2030中国同声传译市场深度调查及投资效益分析报告
- 2025至2030年中国红外热成像仪产业发展态势及投资决策建议报告
- 第五代移动通信设备安装工程造价编制指导意见信息通信建设工程费用定额信息通信建设工程概预算编制规程-2024
- 密集场所安全管理制度
- 休克分类与护理要点
评论
0/150
提交评论