1. //原文:http://www.tuicool.com/articles/IveiQbQ
  2. 创建并且初始化Task
  3. 使用lambda表达式创建Task
  4. Task.Factory.StartNew(() => Console.WriteLine("Hello from a task!"));
  5.  
  6. var task = new Task(() => Console.Write("Hello"));
  7. task.Start();
  8. 用默认参数的委托创建Task
  9. using System;
  10. using System.Threading.Tasks;
  11. namespace MultiThread
  12. {
  13. class ThreadTest
  14. {
  15. static void Main()
  16. {
  17. var task = Task.Factory.StartNew(state => Greet("Hello"), "Greeting");
  18. Console.WriteLine(task.AsyncState); // Greeting
  19. task.Wait();
  20. }
  21. static void Greet(string message) { Console.Write(message); }
  22. }
  23. }
  24. 这种方式的一个优点是,task.AsyncState作为一个内置的属性,可以在不同线程中获取参数的状态。
  25. System.Threading.Tasks.TaskCreateOptions
  26. 创建Task的时候,我们可以指定创建Task的一些相关选项。在.Net .0中,有如下选项:
  27. LongRunning
  28. 用来表示这个Task是长期运行的,这个参数更适合block线程。LongRunning线程一般回收的周期会比较长,因此CLR可能不会把它放到线程池中进行管理。
  29. PreferFairness
  30. 表示让Task尽量以公平的方式运行,避免出现某些线程运行过快或者过慢的情况。
  31. AttachedToParent
  32. 表示创建的Task是当前线程所在Task的子任务。这一个用途也很常见。
  33. 下面的代码是创建子任务的示例:
  34. using System;
  35. using System.Threading;
  36. using System.Threading.Tasks;
  37. namespace MultiThread
  38. {
  39. class ThreadTest
  40. {
  41. public static void Main(string[] args)
  42. {
  43. Task parent = Task.Factory.StartNew(() =>
  44. {
  45. Console.WriteLine("I am a parent");
  46. Task.Factory.StartNew(() => // Detached task
  47. {
  48. Console.WriteLine("I am detached");
  49. });
  50. Task.Factory.StartNew(() => // Child task
  51. {
  52. Console.WriteLine("I am a child");
  53. }, TaskCreationOptions.AttachedToParent);
  54. });
  55. parent.Wait();
  56. Console.ReadLine();
  57. }
  58. }
  59. }
  60. 如果你等待你一个任务结束,你必须同时等待任务里面的子任务结束。这一点很重要,尤其是你在使用Continue的时候。(后面会介绍)
  61. 等待Task
  62. ThreadPool内置的方法中无法实现的等待,在Task中可以很简单的实现了:
  63. using System;
  64. using System.Threading;
  65. using System.Threading.Tasks;
  66. namespace MultiThread
  67. {
  68. class ThreadTest
  69. {
  70. static void Main()
  71. {
  72. var t1 = Task.Run(() => Go(null));
  73. var t2 = Task.Run(() => Go());
  74. Task.WaitAll(t1, t2);//等待所有Task结束
  75. //Task.WaitAny(t1, t2);//等待任意Task结束
  76. }
  77. static void Go(object data) // data will be null with the first call.
  78. {
  79. Thread.Sleep();
  80. Console.WriteLine("Hello from the thread pool! " + data);
  81. }
  82. }
  83. }
  84. 注意:
  85. 当你调用一个Wait方法时,当前的线程会被阻塞,直到Task返回。但是如果Task还没有被执行,这个时候系统可能会用当前的线程来执行调用Task,而不是新建一个,这样就不需要重新创建一个线程,并且阻塞当前线程。这种做法节省了创建新线程的开销,也避免了一些线程的切换。但是也有缺点,当前线程如果和被调用的Task同时想要获得一个lock,就会导致死锁。
  86. Task异常处理
  87. 当等待一个Task完成的时候(调用Wait或者或者访问Result属性的时候),Task任务中没有处理的异常会被封装成AggregateException重新抛出,InnerExceptions属性封装了各个Task没有处理的异常。
  88. using System;
  89. using System.Threading.Tasks;
  90. namespace MultiThreadTest
  91. {
  92. class Program
  93. {
  94. static void Main(string[] args)
  95. {
  96. int x = ;
  97. Task<int> calc = Task.Factory.StartNew(() => / x);
  98. try
  99. {
  100. Console.WriteLine(calc.Result);
  101. }
  102. catch (AggregateException aex)
  103. {
  104. Console.Write(aex.InnerException.Message); // Attempted to divide by 0
  105. }
  106. }
  107. }
  108. }
  109. 对于有父子关系的Task,子任务未处理的异常会逐层传递到父Task,并且最后包装在AggregateException中。
  110. using System;
  111. using System.Threading.Tasks;
  112. namespace MultiThreadTest
  113. {
  114. class Program
  115. {
  116. static void Main(string[] args)
  117. {
  118. TaskCreationOptions atp = TaskCreationOptions.AttachedToParent;
  119. var parent = Task.Factory.StartNew(() =>
  120. {
  121. Task.Factory.StartNew(() => // Child
  122. {
  123. Task.Factory.StartNew(() => { throw null; }, atp); // Grandchild
  124. }, atp);
  125. });
  126. // The following call throws a NullReferenceException (wrapped
  127. // in nested AggregateExceptions):
  128. parent.Wait();
  129. }
  130. }
  131. }
  132. 取消Task
  133. 如果想要支持取消任务,那么在创建Task的时候,需要传入一个CancellationTokenSouce
  134. 示例代码:
  135. using System;
  136. using System.Threading;
  137. using System.Threading.Tasks;
  138. namespace MultiThreadTest
  139. {
  140. class Program
  141. {
  142. static void Main(string[] args)
  143. {
  144. var cancelSource = new CancellationTokenSource();
  145. CancellationToken token = cancelSource.Token;
  146. Task task = Task.Factory.StartNew(() =>
  147. {
  148. // Do some stuff...
  149. token.ThrowIfCancellationRequested(); // Check for cancellation request
  150. // Do some stuff...
  151. }, token);
  152. cancelSource.Cancel();
  153. try
  154. {
  155. task.Wait();
  156. }
  157. catch (AggregateException ex)
  158. {
  159. if (ex.InnerException is OperationCanceledException)
  160. Console.Write("Task canceled!");
  161. }
  162. Console.ReadLine();
  163. }
  164. }
  165. }
  166. 任务的连续执行
  167. Continuations
  168. 任务调度也是常见的需求,Task支持一个任务结束之后执行另一个任务。
  169. Task task1 = Task.Factory.StartNew(() => Console.Write("antecedant.."));
  170. Task task2 = task1.ContinueWith(task =>Console.Write("..continuation"));
  171. Continuations Task<TResult>
  172. Task也有带返回值的重载,示例代码如下:
  173. Task.Factory.StartNew<int>(() => )
  174. .ContinueWith(ant => ant.Result * )
  175. .ContinueWith(ant => Math.Sqrt(ant.Result))
  176. .ContinueWith(ant => Console.WriteLine(ant.Result)); // output 4
  177. 子任务
  178. 前面提到了,当你等待一个任务的时候,同时需要等待它的子任务完成。
  179. 下面代码演示了带子任务的Task
  180. using System;
  181. using System.Threading.Tasks;
  182. using System.Threading;
  183. namespace MultiThreadTest
  184. {
  185. class Program
  186. {
  187. public static void Main(string[] args)
  188. {
  189. Task<int[]> parentTask = Task.Factory.StartNew(() =>
  190. {
  191. int[] results = new int[];
  192. Task t1 = new Task(() => { Thread.Sleep(); results[] = ; }, TaskCreationOptions.AttachedToParent);
  193. Task t2 = new Task(() => { Thread.Sleep(); results[] = ; }, TaskCreationOptions.AttachedToParent);
  194. Task t3 = new Task(() => { Thread.Sleep(); results[] = ; }, TaskCreationOptions.AttachedToParent);
  195. t1.Start();
  196. t2.Start();
  197. t3.Start();
  198. return results;
  199. });
  200. Task finalTask = parentTask.ContinueWith(parent =>
  201. {
  202. foreach (int result in parent.Result)
  203. {
  204. Console.WriteLine(result);
  205. }
  206. });
  207. finalTask.Wait();
  208. Console.ReadLine();
  209. }
  210. }
  211. }
  212. 这段代码的输出结果是: ,,
  213. FinalTask会等待所有子Task结束后再执行。
  214. TaskFactory
  215. 关于TaskFactory,上面的例子中我们使用了System.Threading.Tasks .Task.Factory属性来快速的创建Task。当然你也可以自己创建TaskFactory,你可以指定自己的TaskCreationOptionsTaskContinuationOptions来使得通过你的Factory创建的Task默认行为不同。
  216. .Net中有一些默认的创建Task的方式,由于TaskFactory创建Task的默认行为不同可能会导致一些不容易发现的问题。
  217. 如在.NET .5中,Task加入了一个Run的静态方法:
  218. Task.Run(someAction);
  219. 如果你用这个方法代替上面例子中的Task.Factory.StartNew,就无法得到正确的结果。原因是Task.Run创建Task的行为默认是默认是拒绝添加子任务的。上面的代码等价于:
  220. Task.Factory.StartNew(someAction, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
  221. 你也可以创建具有自己默认行为的TaskFactory
  222. 无论ThreadPool也好,或者Task,微软都是在想进办法来实现线程的重用,来节省不停的创建销毁线程带来的开销。线程池内部的实现可能在不同版本中有不同的机制。如果可能的话,使用线程池来管理线程仍然是建议的选择。
  223. 作者:独上高楼
  224. 出处: http://www.cnblogs.com/myprogram/
  225. 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

Task构造的更多相关文章

  1. Codeforces 959D. Mahmoud and Ehab and another array construction task(构造, 简单数论)

    Codeforces 959D. Mahmoud and Ehab and another array construction task 题意 构造一个任意两个数都互质的序列,使其字典序大等于a序列 ...

  2. Codeforces 461D. Appleman and Complicated Task 构造,计数

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF461D.html 题解 首先我们可以发现如果确定了第一行,那么方案就唯一了. 然后,我们来看看一个点的值确定 ...

  3. cf1088C Ehab and a 2-operation task (构造)

    题意:给一个数列,你可以进行至多n+1次操作,每次给一个前缀对某数取模或者加某数,使得最后数列严格单增 考虑到因为是前缀和而且还不能加负数,光靠加是不能让前面的小于后面的 所以要让他先在模某数意义下单 ...

  4. Codeforces - 1114B - Yet Another Array Partitioning Task - 构造 - 排序

    https://codeforces.com/contest/1114/problem/B 一开始叫我做,我是不会做的,我没发现这个性质. 其实应该很好想才对,至少要选m个元素,其中m个作为最大值,从 ...

  5. 【kAriOJ】离散数学 构造群码 极大似然法解码

    A. 编程题1 构造群码 时间限制 1000 ms 内存限制 65536 KB 题目描述 针对给定H,计算群码编码函数eH,并计算给定字的码字. 输入格式 第一行输入两个整数m,n:(m < n ...

  6. 【Hadoop代码笔记】Hadoop作业提交之TaskTracker获取Task

    一.概要描述 在上上一篇博文和上一篇博文中分别描述了jobTracker和其服务(功能)模块初始化完成后,接收JobClient提交的作业,并进行初始化.本文着重描述,JobTracker如何选择作业 ...

  7. Hadoop作业提交之TaskTracker获取Task

    [Hadoop代码笔记]Hadoop作业提交之TaskTracker获取Task 一.概要描述 在上上一篇博文和上一篇博文中分别描述了jobTracker和其服务(功能)模块初始化完成后,接收JobC ...

  8. C#与C++的发展历程第三 - C#5.0异步编程巅峰

    系列文章目录 1. C#与C++的发展历程第一 - 由C#3.0起 2. C#与C++的发展历程第二 - C#4.0再接再厉 3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰 C#5.0 ...

  9. C#知识点记录

    用于记录C#知识要点. 参考:CLR via C#.C#并发编程.MSDN.百度 记录方式:读每本书,先看一遍,然后第二遍的时候,写笔记. CLR:公共语言运行时(Common Language Ru ...

随机推荐

  1. c#面向对象基础3

    静态与非静态的区别 (1)在非静态类中既可以有实例成员,也可以有静态成员(static修饰). (2)在调用静态成员的时候要使用:对象名.实例成员. (3)在调用静态成员的时候要使用:类名.静态成员. ...

  2. JAVA Spring JavaBean 属性值的注入方式( 属性注入, 特殊字符注入 <![CDATA[ 带有特殊字符的值 ]]> , 构造器注入 )

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  3. 1.Spring AOP (上)

    转自:https://blog.csdn.net/yusheng8711/article/details/21622773 Spring有两大核心,IOC和AOP.IOC在java web项目中无时无 ...

  4. VBA 浏览文件夹

    Private Function SelectFolder() As String        With Application.FileDialog(msoFileDialogFolderPick ...

  5. linux查看网卡驱动

    [root@hudson ~]# yum install ethtool -y [root@hudson ~]# ethtool -i em1driver: bnx2version: 2.2.3fir ...

  6. UGUI Auto Layout 自动布局

    Layout Element 首先分配 Minimum Size 如果还有足够空间,分配 Preferred Size 如果还有额外空间,分配 Flexible Size 比较特别的是 Flexibl ...

  7. Numpy 基础知识

    1.使用ipython --pylab 自动加载 Numpy.Scipy.Matplotlib模块. 创建数组a = arange(10) b = arange(10,dtype='f')c = ar ...

  8. godaddy nginx https 配置

    一. 生成秘钥key,运行: $ openssl genrsa -des3 -out server.key 2048 1 会有两次要求输入密码,输入同一个即可 输入密码 然后你就获得了一个server ...

  9. MapReduce超时原因(Time out after 300 secs)

    目前碰到过三种原因导致 Time out after 300 secs. 1. 死循环 这是最常见的原因.显式的死循环很容易定位,隐式的死循环就比较麻烦了,比如正则表达式.曾经用一个网上抄来的邮箱正则 ...

  10. Mysql修改密码办法

    方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...