Task.WaitAll代替WaitHandle.WaitAll
Task.Waitall阻塞了当前线程直到全完。whenall开启个新监控线程去判读括号里的所有线程执行情况并立即返回,等都完成了就退出监控线程并返回监控数据。
task.Result会等待异步方法返回,当然阻塞住了。别和await 同时用。
Task和ThreadPool的功能类似,可以用来创建一些轻量级的并行任务。对于将一个任务放进线程池
ThreadPool.QueueUserWorkItem(A);
这段代码用Task来实现的话,方式如下:
Task.Factory.StartNew(A);
这两端代码的使用和实现的功能都十分相似。但和TheadPool相比,Task有着更多的功能,更加方便我们使用。
假如我们要创建三个任务,并等待它们完成。这个功能用TheadPool实现如下:
using (ManualResetEvent mre1 = new ManualResetEvent(false))
using (ManualResetEvent mre2 = new ManualResetEvent(false))
using (ManualResetEvent mre3 = new ManualResetEvent(false))
{
ThreadPool.QueueUserWorkItem(delegate
{
A();
mre1.Set();
});
ThreadPool.QueueUserWorkItem(delegate
{
B();
mre2.Set();
});
ThreadPool.QueueUserWorkItem(delegate
{
C();
mre3.Set();
});
WaitHandle.WaitAll(new WaitHandle[] { mre1, mre2, mre3 });
}
用Task类实现起来就相对简单多了:
Task t1 = Task.Factory.StartNew(delegate { A(); });
Task t2 = Task.Factory.StartNew(delegate { B(); });
Task t3 = Task.Factory.StartNew(delegate { C(); });
t1.Wait();
t2.Wait();
t3.Wait();
或者我们还可以这么写:
Task t1 = Task.Factory.StartNew(delegate { A(); });
Task t2 = Task.Factory.StartNew(delegate { B(); });
Task t3 = Task.Factory.StartNew(delegate { C(); });
Task.WaitAll(t1, t2, t3);
下面我们来简单的介绍一下Task的基本用法:
创建Task
创建Task有两种方式
- 通过构造函数创建
Task t1 = new Task(A); - 通过TaskFactory创建
Task t1 = Task.Factory.StartNew(A);
这两种方式其实是一样的,第一种方式里面也传入了默认的TaskFactory——Task.Factory。TaskFactory起着对Task进行创建和调度管理的作用,类似于以前CTP版中的TaskManager,关于这个对象,后续会单独写一篇文章介绍。
开始运行Task
在上述两种创建Task方式中,方式1创建的Task并没有立即执行,需要手动调用t1.Start()来执行(类似于线程,需要手动执行)。而方式2创建的Task是立即执行的(类似于线程池,是自动执行的),从这两种方式的函数名称也可以看出这一点。
等待Task完成
等待Task完成的也有两种:
- 调用Task的成员函数t.Wait()。
- 调用Task的静态函数Task.WaitAll()或Task.WaitAny()。
这两种方式和.net中常用的WaitHandle差不多,这里就不多介绍了。
取消Task
取消Task的方式较CTP的时候复杂和强大了不少,后续加一个单独的篇章单独介绍。
异常处理
当Task在执行过程中发生异常时,该异常会在Wait或WaitAll等函数中重新throw。可以通过Task的Exception属性来获取发生的异常。
var t1 = Task.Factory.StartNew(() => { throw new Exception("t1 error occor"); });
var t2 = Task.Factory.StartNew(() => { throw new Exception("t2 error occor"); });
try
{
Task.WaitAll(t1, t2);
}
catch (Exception)
{
Console.WriteLine(t1.Exception.InnerException.Message);
Console.WriteLine(t2.Exception.InnerException.Message);
}
获取Task的返回值
在CTP版本中,是通过Fucture<>类来获取带返回值的Task的,现在已经将类改名为Task<>了,从而实现命名方式的统一。使用方式几乎一致,就是多了一个Result属性,可以在Task执行完成后获取返回值。示例如下:
var t1 = Task.Factory.StartNew(() => 3);
t1.Wait();
Console.WriteLine(t1.Result);
Task.WaitAll代替WaitHandle.WaitAll的更多相关文章
- WaitHandle.WaitAll 方法在WPF工程中的应用
因为WaiAll需要多线程支持, 而WPF是STA模式, 可以通过以下方式实现WaitAll ManualResetEvent[] events: foreach (ManualResetEvent ...
- WaitAny, WaitAll 和 SignalAndWait
除了Set 和 WaitOne方法外,在类WaitHandle中还有一些用来创建复杂的同步过程的静态方法. WaitAny, WaitAll 和 SignalAndWait使跨多个可能为不同类型的等待 ...
- C# Task 用法
C# Task 的用法 其实Task跟线程池ThreadPool的功能类似,不过写起来更为简单,直观.代码更简洁了,使用Task来进行操作.可以跟线程一样可以轻松的对执行的方法进行控制. 顺便提一下, ...
- 线程 线程池 Task
首先声明 这是读了 愉悦的绅士 文章 <菜鸟之旅——学习线程(线程和线程池)> <Task与线程> 的一些个人总结,还是那句话,如有不对,欢迎指正 文章以代码加注释的方法展示. ...
- .Net4.0并行库介绍——Task
Task和ThreadPool的功能类似,可以用来创建一些轻量级的并行任务.对于将一个任务放进线程池 ThreadPool.QueueUserWorkItem(A); 这段代码用Task来实现 ...
- (译).NET4.X并行任务Task需要释放吗?
摘要:本博文解释在.NET 4.X中的Task使用完后为什么不应该调用Dispose().并且说明.NET4.5对.NET4.0的Task对象进行的部分改进:减轻Task对WaitHandle对象的依 ...
- C# Task的用法
C# Task 的用法 其实Task跟线程池ThreadPool的功能类似,不过写起来更为简单,直观.代码更简洁了,使用Task来进行操作.可以跟线程一样可以轻松的对执行的方法进行控制. 顺便提一下, ...
- 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq
常量,字段,构造方法 常量 1.什么是常量 常量是值从不变化的符号,在编译之前值就必须确定.编译后,常量值会保存到程序集元数据中.所以,常量必须是编译器识别的基元类型的常量,如:Boolean ...
- C#的WaitHandle : 管理多线程状态
有时候,我们创建了多线程,需要知道是否都完成了各自的工作.比如说,开启了多线程的下载,如何终止所有的线程并且在确保所有线程都终止之后才继续执行程序的退出呢? public partial class ...
随机推荐
- linux 3.10 一次softlock排查
x86架构.一个同事分析的crash,我在他基础上再次协助分析,也没有获得进展,只是记录一下分析过程.记录是指备忘,万一有人解决过,也好给我们点帮助. 有一次软锁,大多数cpu被锁,log中第一个认为 ...
- Mybatis高级应用-2
文章内容简介 1.回顾 2.Mybatis配置文件解析 3.Mybatis映射文件解析 ResultMap标签使用 自定义返回值处理(Map) 关联映射 主键映射 一.回顾 Mybatis是ORM(o ...
- React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
昨天在项目中,重新封装组件时,引用了原来的一个子组件,但发现子组件在其他页面正常,在新的组件里面就发生保存, 然后把子组件注释,随便显示其div元素也正常,纠结了很久,最后发现引用的方式有问题 子组件 ...
- Linux sed命令使用方法
sed(Stream Editor)是Linux中文本处理使用非常广泛的工具,可以对文件内容进行替换.删除.新增.选取特定行等功能.下面通过sed常用实例介绍sed命令的使用方法. sed基本语法 s ...
- Linux grep命令使用方法
Linux系统中grep命令可以根据指定的字符串或者正则表达式对文件内容进行匹配查找.在Linux文件处理和SHELL编程中使用广泛. grep基本语法 用法: grep [选项] "字符串 ...
- avalon2学习教程05属性操作
avalon2与avalon1的属性操作虽然都是使用ms-attr,但用法完全不一样. avalon1是这样操作属性的 其语法为 ms-attr-valueName="vmProp" ...
- node-sass:npm install node-sass --save
从git上拉下来的项目,要先安装依赖, 再运行. 缺少node-sass:npm install node-sass --save
- ios嵌套H5页面,出现的小bug;
ios嵌套H5页面,点击数字时就会弹出打电话的功能:解决方法: 在head标签中添加: <meta name="format-detection" content=" ...
- Linux 安装 iptables防火墙
CentOS7默认的防火墙不是iptables,而是firewalle. 安装iptable iptable-service #先检查是否安装了iptables service iptables st ...
- 内核 platform_get_resource() 函数解析
struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, un ...