《C#本质论》读书笔记(18)多线程处理
.NET Framework 4.0 看(本质论第3版)
18.1 独立线程的运行和控制
| 编写 Task 时,需要分配希望 Task 执行的一组指令,然后启动 Task 。指令的分配基本上都靠委托。 |
- class Program
- {
- static void Main(string[] args)
- {
- const int Repettitions = 10000;
- Task task = new Task(() =>
- {
- for (int count = 0; count < Repettitions; count++)
- {
- Console.Write('-');
- }
- });
- task.Start();
- for (int count = 0; count < Repettitions; count++)
- {
- Console.Write('+');
- }
- task.Wait();
- }
- }

问题:我什么时候能使用Task的Start()方法?
- 问题:我什么时候能使用Task的Start()方法?只有 Task 处于 TaskStatus.Created 状态时才能使用实例方法 Start() 。
并且,只有在使用 Task 的公共构造函数构造的 Task 实例才能处于 TaskStatus.Created 状态。 - 问题:使用Task.Run()/Task.ContinueWith()/Task.Factory.StartNew()/TaskCompletionSource/异步方法(即使用async与await关键字的方法)……应该调用Start()方法吗?
不应该。不仅不应该,而且也不能,因为此时调用Start()会报异常。从问题1可知:Start()实例方法只适用于TaskStatus.Created状态的Task。由上面提到的方式创建的Task其状态不是TaskStatus.Created,而是如TaskStatus.WaitingForActivation、TaskStatus.Running或TaskStatus.RanToCompletion。
- static void Main(string[] args)
- {
- Task<string> task = Task.Factory.StartNew<string>(
- > PiCalculator.Calculate(100));
- foreach (char busySymbol in Utility.BusySymbols())
- {
- if (task.IsCompleted)
- {
- Console.Write('\b');
- break;
- }
- Console.Write(busySymbol);
- }
- Console.WriteLine();
- // Blocks until task completes.
- Console.WriteLine(task.Result);
- System.Diagnostics.Trace.Assert(task.IsCompleted);
- }
| 属性 | 解释 |
说明 |
| Status | 指明任务的状态。
Created = 0,
WaitingForActivation = 1,
WaitingToRun = 2,
Running = 3,
WaitingForChildrenToComplete = 4,
RanToCompletion = 5,
Canceled = 6,
Faulted = 7, |
获取此任务的 TaskStatus 枚举 |
| IsComplete | 不管任务是否出错,IsComplete在任务完成后都被设为true,任何时候只要Status为 5,6,7 就为true。 | 获取此 Task 是否已完成 |
| Id | 解决多线程问题(竞争和死锁),Id尤为有用 | 获取此 Task 实例的 ID |
| AsyncState | 能跟踪额外的数据。 | 获取在创建 Task 时提供的状态对象,如果未提供,则为 null |
| Task.CurrentId | 任何地方都可调用,特别适合调试和诊断性类型的活动 | 返回当前正在执行 Task 的 ID |

- public enum TaskStatus
- {
- // 该任务已初始化,但尚未被计划。
- Created = 0,
- // 该任务正在等待 .NET Framework 基础结构在内部将其激活并进行计划。
- WaitingForActivation = 1,
- // 该任务已被计划执行,但尚未开始执行。
- WaitingToRun = 2,
- // 该任务正在运行,但尚未完成。
- Running = 3,
- // 该任务已完成执行,正在隐式等待附加的子任务完成。
- WaitingForChildrenToComplete = 4,
- // 已成功完成执行的任务。
- RanToCompletion = 5,
- // 该任务已通过对其自身的 CancellationToken 引发 OperationCanceledException 异常
- Canceled = 6,
- // 由于未处理异常的原因而完成的任务。
- Faulted = 7,
- }
- class Program
- {
- static void Main(string[] args)
- {
- /* 创建一个任务 不调用 不执行 状态为Created */
- Task tk = new Task(() =>
- {
- });
- Console.WriteLine(tk.Status.ToString());
- /* 创建一个任务 执行 状态为 WaitingToRun */
- Task tk1 = new Task(() =>
- {
- });
- tk1.Start(); /*对于安排好的任务,就算调用Start方法也不会立马启动 此时任务的状态为WaitingToRun*/
- Console.WriteLine(tk1.Status.ToString());
- /* 创建一个主任务 */
- Task mainTask = new Task(() =>
- {
- SpinWait.SpinUntil(() =>
- {
- return false;
- }, 30000);
- });
- /* 将子任务加入到主任务完成之后执行 */
- Task subTask = mainTask.ContinueWith((t1) =>
- {
- });
- /* 启动主任务 */
- mainTask.Start();
- /* 此时子任务状态为 WaitingForActivation */
- Console.WriteLine(subTask.Status.ToString());
- /* 创建一个任务 执行 后 等待一段时间 并行未结束的情况下 状态为 Running */
- Task tk2 = new Task(() =>
- {
- SpinWait.SpinUntil(() => false, 30000);
- });
- tk2.Start(); /*对于安排好的任务,就算调用Start方法也不会立马启动*/
- SpinWait.SpinUntil(() => false, 300);
- Console.WriteLine(tk2.Status.ToString());
- /* 创建一个任务 然后取消该任务 状态为Canceled */
- CancellationTokenSource cts = new CancellationTokenSource();
- Task tk3 = new Task(() =>
- {
- for (int i = 0; i < int.MaxValue; i++)
- {
- if (!cts.Token.IsCancellationRequested)
- {
- cts.Token.ThrowIfCancellationRequested();
- }
- }
- }, cts.Token);
- tk3.Start(); /*启动任务*/
- SpinWait.SpinUntil(() => false, 100);
- cts.Cancel(); /*取消该任务执行 但并非立马取消 所以对于Canceled状态也不会立马生效*/
- SpinWait.SpinUntil(() => false, 1000);
- Console.WriteLine(tk3.Status.ToString() + " " + tk3.IsCanceled);
- SpinWait.SpinUntil(() => false, 1000);
- Console.WriteLine(tk3.Status.ToString() + " " + tk3.IsCanceled);
- SpinWait.SpinUntil(() => false, 1000);
- Console.WriteLine(tk3.Status.ToString() + " " + tk3.IsCanceled);
- /*创建一个任务 让它成功的运行完成 会得到 RanToCompletion 状态*/
- Task tk4 = new Task(() =>
- {
- SpinWait.SpinUntil(() => false, 10);
- });
- tk4.Start();
- SpinWait.SpinUntil(() => false, 300);
- Console.WriteLine(tk4.Status.ToString());
- /*创建一个任务 让它运行失败 会得到 Faulted 状态*/
- Task tk5 = new Task(() =>
- {
- throw new Exception();
- });
- tk5.Start();
- SpinWait.SpinUntil(() => false, 300);
- Console.WriteLine(tk5.Status.ToString());
- Console.ReadLine();
- }
- }
- class Product
- {
- public string Name { get; set; }
- public string Category { get; set; }
- public int SellPrice { get; set; }
- }
18.1.1 ContinueWith()
18.1.2 task上未处理的异常
18.1.3 取消任务
18.1.4 长时间运行任务
18.1.5 释放一个任务
18.2 并行迭代
18.3 并行执行LINQ查询
18.4 .NET4.0之前的多线程处理
18.5 AppPomain 的未处理异常
《C#本质论》读书笔记(18)多线程处理的更多相关文章
- 存储器的保护(一)——《x86汇编语言:从实模式到保护模式》读书笔记18
本文是原书第12章的学习笔记. 说句题外话,这篇博文是补写的,因为让我误删了,可恶的是CSDN的回收站里找不到! 好吧,那就再写一遍,我有坚强的意志.司马迁曰:“文王拘而演<周易>:仲尼厄 ...
- C#本质论读书笔记:第一章 C#概述|第二章 数据类型
第一章 1.字符串是不可变的:所有string类型的数据,都不可变,也可以说是不可修改的,不能修改变量最初引用的数据,只能对其重新赋值,让其指向内存中的一个新位置. 第二章 2.1 预定义类型或基本类 ...
- 《Linux内核设计与实现》读书笔记 18
第十八章调试 18.1 准备开始 一个bug:大部分bug通常都不是行为可靠而且定义明确的 一个藏匿bug的内核版本:找出bug首先出现的版本 相关内核代码的知识和运气 18.2内核中的bug 可以有 ...
- 『TCP/IP详解——卷一:协议』读书笔记——18
2013-08-27 15:44:52 第7章 Ping程序 7.1 引言 “ping”这个名字来源于声纳定为操作.Ping程序由Mike Muuss编写,目的是为了测试另一台主机是否可达.该程序发送 ...
- OCP读书笔记(18) - 空间管理
OLTP 表压缩 压缩始终是非常占用CPU的过程,并且需要花费一定时间,通常,如果压缩数据,则数据必须解压缩后才能使用.虽然此要求在数据仓库环境中是可以接受的但在OLTP环境中可能无法接受 现在,在O ...
- OCA读书笔记(18) - 使用Support工具
调查和解决问题 问题:数据库中的任一严重的错误定义为一个问题,一般来说,这些错误包括大家熟悉的ORA-600错误和ORA-04031(共享池超出)错误,涉及数据库问题的所有元数据都存储在ADR中,每个 ...
- 《http权威指南》读书笔记18
概述 最近对http很感兴趣,于是开始看<http权威指南>.别人都说这本书有点老了,而且内容太多.我个人觉得这本书写的太好了,非常长知识,让你知道关于http的很多概念,不仅告诉你怎么做 ...
- 存储器的保护(三)——《x86汇编语言:从实模式到保护模式》读书笔记20
存储器的保护(三) 修改本章代码清单,使之可以检测1MB以上的内存空间(从地址0x0010_0000开始,不考虑高速缓存的影响).要求:对内存的读写按双字的长度进行,并在检测的同时显示已检测的内存数量 ...
- 《TCP/IP详解卷1:协议》第17、18章 TCP:传输控制协议(1)-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
随机推荐
- 1 python大数据挖掘系列之基础知识入门
preface Python在大数据行业非常火爆近两年,as a pythonic,所以也得涉足下大数据分析,下面就聊聊它们. Python数据分析与挖掘技术概述 所谓数据分析,即对已知的数据进行分析 ...
- 遍历hashMap的两种方式
第一种: Map map = new HashMap(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Ma ...
- mysql的优化
1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽 ...
- maven热部署到tomcat
1添加tomcat用户,在conf/tomcat-user.xml文件下添加一个tomcat用户 <role rolename="manager-gui"/> < ...
- 美团HD(3)-加载分类导航数据
DJHomeViewController.m /** 设置导航栏左侧内容 */ - (void)setupLeftNavItem { // Logo UIImageView *logoView = [ ...
- .htaccess基本语法和应用 (2012-11-09 16:13:47)转载▼
htaccess基本语法和应用 (2012-11-09 16:13:47) 转载▼ 标签: htaccess it 分类: 网络 .htaccess是Apache服务器的一个非常强大的分布式配置文件 ...
- 纯JS实现俄罗斯方块,打造属于你的游戏帝国
纯JS俄罗斯方块,打造属于你的游戏帝国. 本文原始作者博客 http://www.cnblogs.com/toutou 俄罗斯方块(Tetris, 俄文:Тетрис)是一款电视游戏机和掌上游戏机游戏 ...
- Max double slice sum 的解法
1. 上题目: Task description A non-empty zero-indexed array A consisting of N integers is given. A tripl ...
- 2016icpc大连站总结(呐 如果把这段回忆,起个名字珍藏起来,叫它“宝物”应该很合适吧)
10月15号一早乘飞机去了大连,12点这样到了海事大学,是一所很大的学校,来往的学生有些穿着海军服.然后我们到体育馆领了衣服,就去食堂吃午饭,中间有段小插曲,就是我们队的餐券没领..不过那里的负责人让 ...
- 在Web工程中引入Jquery插件报错解决方案
在学习Jquery插件的时候,遇到一个问题就是新建web工程后在WebRoot下引入Jquery插件的时候报错,不知道为什么好纠结,但是项目能正常运行,后来找到解决方案,在这里给大家分享一下. 解决方 ...