1.Task概述:Task是对操作系统线程的抽象,目的是使线程池能高效地管理线程的分配和回收,Task使用的底层线程属于一种共享资源,任务需要互相协作,并及时归还线程,以便用相同的共享资源(线程)满足其他请求。

2.Task.AsyncState:获取在创建 Task 时提供的状态对象,如果未提供,则为 null。若状态对象在task内部改变了,AsyncState的数据也是改变后的状态对象。可查看ThreadApply.TaskAsyncState()方法的代码。

3.Task.ContinueWith():它的作用是把任务链接起来,在父任务完成后会立即执行后续任务。若在父任务的实例上多次调用ContinueWith()方法,在父任务完成后,所添加的后续任务会并行执行。当然可以根据TaskContinuationOptions枚举来指定根据父任务的执行情况,来执行后续任务。

4.Task的异常:Task执行期间产生的未处理的异常后会被禁止,直到调用某个任务完成(Task)成员,如Wait()、Result、WaitAll()、WaitAny(),上述的成员都会引发在任务执行期间发生的未处理异常。可查看代码TreadApply.TaskException()。

5.Task的异常2:要在不使用try/catch块的情况下处理未处理的异常,另一个办法是使用ContinueWith()任务,利用ContinueWith()委托的task参数,可以评估父任务的Exception属性,可查看代码TreadApply.TaskException2()。

6.Task的取消:可查看代码ThreadApply.TaskCancellationToken()方法,需要用到CancellationTokenSource类,对CancellationTokenSource.Cancel()方法的调用,会在从CancellationTokenSource.Token复制的所有取消标志上设置IsCancellationRequested属性。此中需要注意的2点,

(1)取消标志:CancellationToken(而不是CancellationTokenSource)会在异步任务中求值,CancellationToken看起来和CancellationTokenSource差不多。但CancellationToken用于监视和响应一个取消请求,而CancellationTokenSource用于取消任务本身。

(2)复制的:CancellationToken 是一个struct,所以调用CancellationTokenSource.Token会创建标志的一个副本,这样一来所有取消标志的实例都是线程安全的。

7.长时间运行的任务:如果开发人员知道一个Task要长时间运行,会长时间“霸占”一个底层线程资源,开发人员应告诉线程池共享线程不会太快交还。这样一来,线程池更有可能为任务创建一个专用线程(而不是分配其中的一个共享线程),为此,在调用StartNew()时,要使用TaskCreationOption.LongRunning选项。

8.并行迭代:.net4.0中新增了2个并行迭代,分别为Parallel.For()与Parallel.Foreach()。API会判断同时执行多少个线程才是效率最高的,可查看ThreadApply.ParallelFor()与ThreadApply.ParallelForeach()方法的代码。

9.并行异常的处理:在并行处理时,在并行的内容中可能出现多个异常,那么其异常信息会归到AggregateException异常类型,它是包含了多个内部异常的一个异常。System.Threading.Task命名空间一致使用System.AggregateException对未处理的异常进行分组,因为对于并行操作,经常都可能产生多个异常。如ThreadApply.ParallelForeach()代码清单。

10.并行循环的取消:Task需要一个显式调用才能阻塞(它的调用线程,并一直等)到它完成,并行循环虽然和任务不同,它以并行方式执行迭代,但它仍会阻塞(它的调用线程,并一直等)到整个Parallel.For()或Parallel.ForEach()循环结束。所以为了取消并行循环,调用取消请求的那个线程通常不能是正在执行并行循环的那个线程。如代码ThreadApply.CancelParallelForeach()清单。

11.并行迭代的中断:和标准的for循环相似,Parallel的循环也支持中断(ParallelLoopState.Break())以退出循环并取消进一步迭代的概念。但是,在并行执行的上下文中,中断循环意味着中断迭代之后的新迭代不应开始,当前正在执行的迭代还是会继续运行直至完成的。要想知道执行了一次中断的最低的迭代,并了解中断是否阻止了一个或多个迭代启动,可查看并行For()/ForEach()方法返回的ParallelLoopResult对象(其含有IsCompleted、LowestBreakIteration属性)。

12.并行Linq查询:并行Linq的功能都在System.Linq.ParallelEnumerable类中,该类的方法形式与System.Linq.Enumerable类的方法形式基本一致,ParallelEnumerable类中有对IEnumerable<T>类型,进行转化为并行的处理类型的扩展方法,即IEnumerable<T>.AsParallel()。只有在执行此转化后,才能对集合进行并行处理。

13.并行Linq的异常:与并行For和Foreach一样,PLinq运算也可能因为完全相同的原因返回多个异常(不同的迭代同时执行),幸好,捕获异常的机制也是一样。PLinq异常可以通过AggregateException的InnerException属性来访问,因此,将一个Plinq查询包装到一个try/catch块中,并捕捉AggregateException类型的异常,就可以处理每一次迭代中的未处理异常。

14.取消PLinq查询:和并行循环相似,取消的PLinq查询会引发一个OperationCanceledException,另外,PLinq查询会阻塞调用线程,直到查询完成。所以应该把并行Linq包装在Task中。在使用取消PLinq功能前,需要对并行集合执行WithCancellation()方法,如代码TreadApply.CancelParallelLinq()清单。

15.异步类使用说明:在选择要使用的异步类时,按照优选顺序从高到低依次是Task、ThreadPool、Thread。换而言之,首选TPL,如果不合适,就是使用ThreadPool,如果还是不合适就用Thread。

16.AppDomain的未处理异常:在主应用程序上,如果要登记一个回调方法来接收关于未处理的异常通知,只需要向应用程序域的UnhandledException事件注册即可。可查看ThreadApply.AppDomainException()代码清单,应用程序域的线程(包括主线程)上发生任何未处理的异常,都会触发UnhandledException回调,这只是一个通知机制,而不是实际捕捉和处理异常以使应用程序能继续运行的机制。事件发生之后,应用程序会退出。

  1. public class ThreadApply
  2. {
  3. public void TaskCreate()
  4. {
  5. int times = ;
  6. Task task = new Task(() =>
  7. {
  8. for (int i = ; i < times; i++)
  9. {
  10. Console.Write("-");
  11. }
  12. });
  13. task.Start();
  14. for (int i = ; i < times; i++)
  15. {
  16. Console.Write(".");
  17. }
  18. task.Wait();
  19. }
  20.  
  21. public void TaskStaticCreate()
  22. {
  23. Task<string> task = Task.Factory.StartNew(() =>
  24. {
  25. Thread.Sleep();
  26. return "主神";
  27. });
  28. foreach (char busySymbol in Utility.BusySymbols())
  29. {
  30. if (task.IsCompleted)
  31. {
  32. Console.Write('\b');
  33. break;
  34. }
  35. Console.Write(busySymbol);
  36. }
  37. Console.WriteLine();
  38. Console.WriteLine(task.Result);
  39. Console.WriteLine(task.Status);
  40. Trace.Assert(task.IsCompleted);
  41. }
  42.  
  43. public void TaskAsyncState()
  44. {
  45. Man man = new Man() { Name = "主神", Age = };
  46. Task task = Task.Factory.StartNew((_man) =>
  47. {
  48. Man tempMan = (Man)_man;
  49. Console.WriteLine("执行前{0}", tempMan);
  50. tempMan.Name = "诸神";
  51. tempMan.Age += ;
  52. Console.WriteLine("执行后{0}", tempMan);
  53. }, man);
  54. task.Wait();
  55. Console.WriteLine("原始{0},异步后{1}", man, task.AsyncState);
  56. }
  57.  
  58. public void TaskContinueWith()
  59. {
  60. Task<string> task = Task<string>.Factory.StartNew(() =>
  61. {
  62. Console.WriteLine("主任务");
  63. Thread.Sleep();
  64. return "红星";
  65. });
  66. Task faultedTask = task.ContinueWith((antecedentTask) =>
  67. {
  68. Trace.Assert(antecedentTask.IsFaulted);
  69. Console.WriteLine("Task State: Faulted");
  70. }, TaskContinuationOptions.OnlyOnFaulted);
  71. Task cancelTask = task.ContinueWith((antecedentTask) =>
  72. {
  73. Trace.Assert(antecedentTask.IsCanceled);
  74. Console.WriteLine("Task State: Canceled");
  75. }, TaskContinuationOptions.OnlyOnCanceled);
  76. Task completedTask = task.ContinueWith((antecedentTask) =>
  77. {
  78. Trace.Assert(antecedentTask.IsCompleted);
  79. Console.WriteLine("Task Result:{0}", antecedentTask.Result);
  80. Console.WriteLine("Task State: Completed");
  81. }, TaskContinuationOptions.OnlyOnRanToCompletion);
  82. completedTask.Wait();//这句代码可以不用,仅仅是为了阻止控制台关闭
  83. }
  84.  
  85. public void TaskException()
  86. {
  87. //此处代码的演示了未处理的框架,如何将任务的未处理的异常传回给主线程,注意异常的数据类型是异常集合AggregateException,
  88. Task task = Task.Factory.StartNew(() => { throw new ApplicationException(); });
  89. try
  90. {
  91. task.Wait();
  92. }
  93. catch (AggregateException ex)
  94. {
  95. foreach (Exception item in ex.InnerExceptions)
  96. {
  97. Console.WriteLine("error : {0}", item.Message);
  98. }
  99. }
  100. }
  101.  
  102. public void TaskException2()
  103. {
  104. /*Task task = Task.Factory.StartNew(() => { throw new ApplicationException(); });
  105. Task faultedTask = task.ContinueWith(antecedentTask => { Console.WriteLine("父任务执行失败"); }, TaskContinuationOptions.OnlyOnFaulted);
  106. faultedTask.Wait();
  107. if (task.IsFaulted)
  108. {
  109. Console.WriteLine("Error: {0}", task.Exception.Message);//task的异常类型为AggregateException
  110. }*/
  111. Task task = Task.Factory.StartNew(() => { throw new ApplicationException(); });
  112. Task faultedTask = task.ContinueWith(antecedentTask =>
  113. {
  114. foreach (var item in antecedentTask.Exception.InnerExceptions)
  115. {
  116. Console.WriteLine("Error:{0}", item.Message);
  117. }
  118. Console.WriteLine("父任务执行失败");
  119. }, TaskContinuationOptions.OnlyOnFaulted);
  120. faultedTask.Wait();
  121. }
  122.  
  123. public void TaskCancellationToken()
  124. {
  125. string stars = "*".PadRight(, '*');
  126. Console.WriteLine("Push Enter to exit.");
  127. CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
  128. Task task = Task.Factory.StartNew(() => Utility.WriteNaturalNumber(cancellationTokenSource.Token), cancellationTokenSource.Token);
  129. Thread.Sleep();
  130. Console.WriteLine();
  131. cancellationTokenSource.Cancel();
  132. Console.WriteLine(stars);
  133. task.Wait();
  134. Console.WriteLine("Task Status: {0}", task.Status);
  135. //在任务中是正常取消的,所以任务的状态是RanToCompletion。若要状态为Canceled,可是使用CancellationToken.ThrowIfCancellationRequested()方法,报告异常。
  136. }
  137.  
  138. public void ParallelFor()
  139. {
  140. Parallel.For(, , (i) =>
  141. {
  142. Console.WriteLine("第{0}次,threadId={1}", i, Thread.CurrentThread.ManagedThreadId);
  143. });
  144. }
  145.  
  146. public void ParallelForeach()
  147. {
  148. IEnumerable<string> files = Directory.GetFiles("D:\\", "*.txt", SearchOption.AllDirectories);
  149. try
  150. {
  151. Parallel.ForEach(files, (fileName) =>
  152. {
  153. //Encrypt(fileName);
  154. });
  155. }
  156. catch (AggregateException ex)
  157. {
  158. foreach (var item in ex.InnerExceptions)
  159. {
  160. Console.WriteLine(item.Message);
  161. }
  162. }
  163. }
  164.  
  165. public void CancelParallelForeach()
  166. {
  167. IEnumerable<string> files = Directory.GetFiles("D:\\", "*.txt", SearchOption.AllDirectories);
  168. CancellationTokenSource cts = new CancellationTokenSource();
  169. ParallelOptions parallelOptions = new ParallelOptions() { CancellationToken = cts.Token };
  170. cts.Token.Register(() => Console.WriteLine("Cancelling..."));
  171. Console.WriteLine("Push Enter to exit.");
  172. Task task = Task.Factory.StartNew(() =>
  173. {
  174. //注意,在内部,并行循环条件通过IsCancellationRequested属性阻止尚未开始的新迭代开始。
  175. Parallel.ForEach(files, parallelOptions, (fileName, loopState) =>
  176. {
  177. //Encrypt(fileName);
  178. });
  179. });
  180. Console.ReadLine();
  181. cts.Cancel();
  182. Console.WriteLine("---------分割线----------");
  183. task.Wait();
  184. }
  185.  
  186. public void ParalleEncrypt(List<string> data)
  187. {
  188. ParallelQuery<string> result = data.AsParallel().Select(item => Utility.Encrypt(item));
  189. }
  190.  
  191. public void CancelParallelLinq()
  192. {
  193. IEnumerable<int> data = Enumerable.Range(, );
  194. CancellationTokenSource cts = new CancellationTokenSource();
  195. Console.WriteLine("Push Enter to exit.");
  196. Task task = Task.Factory.StartNew(() =>
  197. {
  198. data.AsParallel().WithCancellation(cts.Token).Select(item =>
  199. {
  200. Thread.Sleep();//模拟损耗的时间
  201. return item >> ;
  202. });
  203. }, cts.Token);
  204. /*CancellationToken除了要传给WithCancellation(),还要作为StartNew()的第二个参数传递,这会造成Task.Wait()引发一个AggregateException,
  205. 它的InnerException属性会被设为一个TaskCanceledAException*/
  206. Console.ReadLine();
  207. cts.Cancel();
  208. Console.WriteLine("------------分割线----------------");
  209. try
  210. {
  211. task.Wait();
  212. }
  213. catch (AggregateException ex)
  214. {
  215. foreach (Exception item in ex.InnerExceptions)
  216. {
  217. Console.WriteLine(item.Message);
  218. }
  219. }
  220. }
  221.  
  222. public void AppDomainException()
  223. {
  224. try
  225. {
  226. AppDomain.CurrentDomain.UnhandledException += Utility.OnUnHandledException;
  227. ThreadPool.QueueUserWorkItem(state => { throw new Exception("不可饶恕"); });
  228. Thread.Sleep();
  229. Console.WriteLine("Still Running...");
  230. }
  231. finally
  232. {
  233. Console.WriteLine("Exiting....");
  234. }
  235. }
  236.  
  237. public class Man
  238. {
  239. public string Name { get; set; }
  240. public int Age { get; set; }
  241. public override string ToString()
  242. {
  243. return string.Format("Name:{0},Age:{1}", Name, Age);
  244. }
  245. }
  246. }
  247.  
  248. public class Utility
  249. {
  250. public static IEnumerable<char> BusySymbols()
  251. {
  252. string busySymbols = @"-\|/-\|/";
  253. int next = ;
  254. while (true)
  255. {
  256. yield return busySymbols[next];
  257. next = ++next % busySymbols.Length;
  258. yield return '\b';
  259. }
  260. }
  261. /// <summary>
  262. /// 输出自然数
  263. /// </summary>
  264. /// <param name="cancellationToken">取消标记</param>
  265. public static void WriteNaturalNumber(CancellationToken cancellationToken)
  266. {
  267. int num = ;
  268. while (!cancellationToken.IsCancellationRequested)
  269. {
  270. Thread.Sleep();
  271. Console.Write("{0},", num++);
  272. }
  273. }
  274.  
  275. public static string Encrypt(string text)
  276. {
  277. throw new NotImplementedException();
  278. }
  279.  
  280. public static void OnUnHandledException(object sender, UnhandledExceptionEventArgs e)
  281. {
  282. Exception exception = (Exception)e.ExceptionObject;
  283. Console.WriteLine("Error {0}:{1} -->{2}", exception.GetType().Name, exception.Message, exception.InnerException.Message);
  284. }
  285. }

--------------以上内容根据《C#本质论 第三版》进行整理

C#学习笔记13的更多相关文章

  1. Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法

    Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法 这篇笔记将介绍如何使用Ext.Net GridPanel 中使用Sorter. 默认情况下,Ext.Net GridP ...

  2. SQL反模式学习笔记13 使用索引

    目标:优化性能 改善性能最好的技术就是在数据库中合理地使用索引.  索引也是数据结构,它能使数据库将指定列中的某个值快速定位在相应的行. 反模式:无规划的使用索引 1.不使用索引或索引不足 2.使用了 ...

  3. golang学习笔记13 Golang 类型转换整理 go语言string、int、int64、float64、complex 互相转换

    golang学习笔记13 Golang 类型转换整理 go语言string.int.int64.float64.complex 互相转换 #string到intint,err:=strconv.Ato ...

  4. springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定

    springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...

  5. Python3+Selenium3+webdriver学习笔记13(js操作应用:弹出框无效如何处理)

    #!/usr/bin/env python# -*- coding:utf-8 -*-'''Selenium3+webdriver学习笔记13(js操作应用:弹出框无效如何处理)'''from sel ...

  6. 并发编程学习笔记(13)----ConcurrentLinkedQueue(非阻塞队列)和BlockingQueue(阻塞队列)原理

    · 在并发编程中,我们有时候会需要使用到线程安全的队列,而在Java中如果我们需要实现队列可以有两种方式,一种是阻塞式队列.另一种是非阻塞式的队列,阻塞式队列采用锁来实现,而非阻塞式队列则是采用cas ...

  7. python 学习笔记 13 -- 经常使用的时间模块之time

    Python 没有包括相应日期和时间的内置类型.只是提供了3个相应的模块,能够採用多种表示管理日期和时间值: *    time 模块由底层C库提供与时间相关的函数.它包括一些函数用于获取时钟时间和处 ...

  8. MiZ702学习笔记13——ZYNQ通过AXI-Lite与PL交互

    在<MiZ702学习笔记7——尝试自制带总线IP>,我曾提到了AXI4-Lite的简单用法,驱动了下流水灯,只涉及到了写总线.今天,我想利用之前的VGA模块,将AXI4-Lite的读写都应 ...

  9. 【干货】Html与CSS入门学习笔记1-3

    从23号开始用了4天时间看完了<Head First Html与CSS>这本书,本书讲解方式深入浅出,便于理解,结合习题,便于记忆,是一本不错的入门书.下面是本书的学习笔记: 一.认识HT ...

  10. AMQ学习笔记 - 13. Spring-jms的配置

    概述 如何使用spring-jms来简化jms客户端的开发? 这篇文章主要记录如何配置以便以后复用,而非原理的讲解,有些内容我 没有掌握原理. producer端 producer端负责发送,这里使用 ...

随机推荐

  1. IIS发布的网页上传文件被拒绝

    在IIS所在的服务器共享的权限(如下图示,但注意不是加everyone)和共享文件夹的权限里都加上IIS_USER完全控制,如果不行再加上NETWORK SERVICE权限

  2. bzoj2395 [Balkan 2011]Timeismoney(最小乘积生成树+计算几何)

    题意 每条边有两个权值\(c,t\),请求出一颗生成树,使得\(\sum c\times \sum t\)最小 题解 为什么生成树会和计算几何扯上关系-- 对于每棵树,设\(x=c,y=t\),我们可 ...

  3. struts2配置文件中的method={1}详解

    struts.xml中的配置: <!-- 配置用户模块的action --> <action name="user_*" class="userActi ...

  4. flink学习笔记-flink实战

    说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...

  5. 学习TypeScript,笔记一:TypeScript的简介与数据类型

    该文章用于督促自己学习TypeScript,作为学笔记进行保存,如果有错误的地方欢迎指正 2019-03-27  16:50:03 一.什么是TypeScript? TypeScript是javasc ...

  6. js 有用信息集

    1.java.cookie.js 库:轻易操作cookie 2.jquery.form.js 库:通过ajaxForm,ajaxsubmit 两个函数,将form转为ajax提交方式:https:// ...

  7. 基础问题:设置radio、select、checkbox 的readonly 属性

    编辑记录的时候,有时候需要禁止用户修改某些项目,常用的方法有以下两种: 1>设置表单的readonly属性问题:但是readonly属性对radio.select.checkbox这三个表单不起 ...

  8. 包括ES6在内的数组操作(待更)

    下面是我对ES6和古老的JS(ES3)一些数组操作的总结,附带了一些我曾经用上的. map处有待更内容. 贴一下有借鉴的网站:https://segmentfault.com/a/1190000002 ...

  9. 108th LeetCode Weekly Contest Binary Subarrays With Sum

    In an array A of 0s and 1s, how many non-empty subarrays have sum S? Example 1: Input: A = [1,0,1,0, ...

  10. PIE SDK栅格生成等值线、面

      1.算法功能简介 等值线图能直观地展示数据的变化趋势,是众多领域展示成果的重要图建之一,被广泛应用于石油勘探.矿物开采.气象预报等众多领域.等值线的绘制是指从大量采样数据中提取出具有相同值的点的信 ...