转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html
.Net多线程编程—任务Task
1 System.Threading.Tasks.Task简介
一个Task表示一个异步操作,Task的创建和执行是独立的。
只读属性:
返回值 |
名称 |
说明 |
object |
AsyncState |
表示在创建任务时传递给该任务的状态数据 |
TaskCreationOptions |
CreationOptions |
获取用于创建此任务的 TaskCreationOptions |
CurrentId |
当前正在执行 Task 的 ID |
|
AggregateException |
Exception |
获取导致 AggregateException 提前结束的 Task。如果 Task 成功完成或尚未引发任何异常,则返回 null |
TaskFactory |
Factory |
提供对用于创建 Task 和 Task<TResult> 的工厂方法的访问 |
int |
Id |
获取此 Task 实例的 ID |
bool |
IsCanceled |
指明此 Task 实例是否由于被取消的原因而已完成执行 |
bool |
IsCompleted |
指明此 Task 是否已完成 |
bool |
IsFaulted |
指明Task 是否由于未经处理异常的原因而完成 |
TaskStatus |
Status |
获取此任务的 TaskStatus |
2 Task状态和生命周期
一个Task实例只会完成其生命周期一次,当Task达到它的3种可能的最终状态之一时,它就再也回不去之前的状态了。任务的生命周期从TaskStatus.Created状态真正开始。
1) 初始状态:
Task实例有三种可能的初始状态
值 |
说明 |
TaskStatus.Created |
该任务已初始化,但尚未被计划。使用Task构造函数创建Task实例时的初始状态。 |
TaskStatus.WaitingForActivation |
该任务正在等待 .NET Framework 基础结构在内部将其激活并进行计划。一个任务的初始状态,这个任务只有当其依赖的任务完成之后才会被调度。 |
TaskStatus.WaitingToRun |
该任务已被计划执行,但尚未开始执行。使用TaskFactory.StartNew创建的任务的初始状态。 |
2)中间状态:
Task实例有两种可能的中间状态
值 |
说明 |
TaskStatus.Running |
该任务正在运行,但尚未完成 |
TaskStatus.WaitingForChildrenToComplete |
该任务已完成执行,正在隐式等待附加的子任务完成 |
3) 最终状态:
Task实例有三种可能的最终状态
值 |
说明 |
TaskStatus.Canceled |
该任务已通过对其自身的 CancellationToken 引发OperationCanceledException 对取消进行了确认,此时该标记处于已发送信号状态;或者在该任务开始执行之前,已向该任务的 CancellationToken 发出了信号。Task属性IsFaulted被设置为true |
TaskStatus.Faulted |
由于未处理异常的原因而完成的任务。Task属性IsCanceled被设置为true |
TaskStatus.RunToCompletion |
已成功完成执行的任务。Task属性IsCompleted被设置为true,IsFaulted和IsCanceled被设置为false |
3 创建并执行任务
1)public Task StartNew(Action action)
参数:
action:要异步执行的操作委托
返回值:
已启动的 System.Threading.Tasks.Task
异常:
System.ArgumentNullException:当 action 参数为 null 时引发的异常。
2)public static Task Run(Action action)
参数:
action:表示在线程池执行的队列的任务
返回值:
已启动的 System.Threading.Tasks.Task
异常:
System.ArgumentNullException:当 action 参数为 null 时引发的异常。
3)public void Start()
启动 System.Threading.Tasks.Task,并将它安排到当前的 System.Threading.Tasks.TaskScheduler中执行。
异常:
System.ObjectDisposedException:已释放 System.Threading.Tasks.Task 实例。
System.InvalidOperationException:System.Threading.Tasks.Task 未处于有效状态,无法启动。 它可能已启动、已执行或已取消,或者可能已经不支持以直接计划的方式创建。
注意:
仅使用Task的构造器来创建Task的实例并不能启动任务,还要使用Start才能启动任务。
4)Task.Factory.StartNew与Task.Run
Task.Factory.StartNew重载方法提供更多的参数,可以控制如何计划执行任务以及如何向调试器公开计划任务的机制和控制任务的创建和执行的可选行为。
而Task.Run提供的方法则不具有上述控制机制。
4 等待任务完成
1)public void Wait()
等待 System.Threading.Tasks.Task 完成执行过程
异常:
ObjectDisposedException:Task 对象已被释放。
AggregateException:System.Threading.Tasks.Task 已取消或在 System.Threading.Tasks.Task 的执行期间引发了异常。如果任务已被取消,System.AggregateException将包含其System.AggregateException.InnerExceptions 集合中的 System.OperationCanceledException。
2)public static void WaitAll(params Task[] tasks)
参数:
tasks:要等待的 Task 实例的数组
异常:
ObjectDisposedException:一个或多个 Task 中的对象 tasks 已被释放。
ArgumentNullException:tasks 参数为 null或tasks 参数包含 null 元素。
AggregateException:在至少一个 Task 实例已取消。如果任务已被取消, AggregateException 异常包含OperationCanceledException 中的异常其 AggregateException.InnerExceptions 集合。或在至少一个执行期间引发了异常 Task 实例。
说明:
主线程会等待作为参数传入的任务tasks执行结束才会执行下一条语句。
3)public static int WaitAny(params Task[] tasks)
参数:
tasks:要等待的 Task 实例的数组
异常:
System.ObjectDisposedException:System.Threading.Tasks.Task 已被释放。
System.ArgumentNullException:tasks 参数为 null。
System.ArgumentException:tasks 参数包含 null 元素。
5 取消任务
使用System.Threading.CancellationToken和System.Threading.CancellationTokenSource中断Task的执行。
1)System.Threading.CancellationToken
传播有关应取消操作的通知
属性:
public bool IsCancellationRequested { get; }
方法:
public void ThrowIfCancellationRequested();
如果已请求取消此标记,则引发 System.OperationCanceledException。
异常:
System.OperationCanceledException:该标记已请求取消。
System.ObjectDisposedException:关联的System.Threading.CancellationTokenSource已被释放。
2) System.Threading.CancellationTokenSource
通知 System.Threading.CancellationToken,告知其应被取消
属性:
public CancellationToken Token { get; }:获取与此 System.Threading.CancellationTokenSource 关联的 System.Threading.CancellationToken。
异常:
System.ObjectDisposedException:已释放标记源。
方法:
public void Cancel():传达取消请求。
异常:
System.ObjectDisposedException:此 System.Threading.CancellationTokenSource 已被释放。
System.AggregateException:聚合异常包含由相关联的 System.Threading.CancellationToken 上已注册的回调引发的所有异常。
6 任务的返回值
1)Task类型
在第1节中已经介绍了Task。
2)Task<TResult>类型
属性
定义 |
说明 |
public static TaskFactory<TResult> Factory { get; } |
提供对用于创建 System.Threading.Tasks.Task<TResult> 实例的工厂方法的访问。 |
public TResult Result { get; } |
获取此 System.Threading.Tasks.Task<TResult>的结果值 |
方法
public Task ContinueWith(Action<Task<TResult>> continuationAction)
参数:
continuationAction:在 System.Threading.Tasks.Task<TResult> 完成时要运行的操作。在运行时,委托将作为一个参数传递给完成的任务。
异常:
System.ObjectDisposedException:System.Threading.Tasks.Task<TResult> 已被释放。
System.ArgumentNullException:continuationAction 参数为 null。
注意:
- 该方法的重载方法提供了更多的控制机制。可以传入CancellationToken、TaskContinuationOptions、TaskScheduler参数。
- 使用Task.Factory.StartNew方法,如果传入的委托无返回值,那么方法执行的返回结果类型其实是Task<TResult>,通过Task<TResult>类型的Result 属性可以查看返回结果。对于串联的多个任务,若后续的任务要使用上一个任务的结果,那么Task.Factory.StartNew返回值类型必须是Task<TResult>或var。
- 返回值可以是自定义类型。
7 TaskCreationOptions (枚举类型)
用途:控制任务创建与执行的行为。
值 |
说明 |
TaskCreationOptions.None |
指定应使用默认行为 |
TaskCreationOptions.PreferFairness |
提示 System.Threading.Tasks.TaskScheduler 以一种尽可 能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行 |
TaskCreationOptions.LongRunning |
指定某个任务将是运行时间长、粗粒度的操作。 它会向 System.Threading.Tasks.TaskScheduler 提示,过度订阅可能是合理的。 |
TaskCreationOptions.AttachedToParent |
指定将任务附加到任务层次结构中的某个父级 |
TaskCreationOptions.DenyChildAttach |
如果尝试附有子任务到创建的任务,指定 System.InvalidOperationException 将被引发 |
TaskCreationOptions.HideScheduler |
防止环境计划程序被视为已创建任务的当前计划程序。 这意味着像 StartNew 或 ContinueWith 创建任务的执行操作将被视为 System.Threading.Tasks.TaskScheduler.Default当前计划程序 |
8 任务计划TaskScheduler
功能:扩展任务执行计划,例如自定义任务计划程序来实现性能加速。
属性:
名称 |
说明 |
Current |
当前正在执行的任务关联的 TaskScheduler |
Id |
TaskScheduler 的唯一 ID |
MaximumConcurrencyLevel |
指示此 TaskScheduler 能够支持的最大并发级别 |
9 串联多个任务
1)public Task ContinueWith(Action<Task> continuationAction);
参数:
continuationAction:在 System.Threading.Tasks.Task 完成时要运行的操作。 在运行时,委托将作为一个参数传递给完成的任务。
异常:
System.ObjectDisposedException:创建了 cancellationToken 的 System.Threading.CancellationTokenSource已经被释放。
System.ArgumentNullException:continuationAction 参数为 null。
2)public Task ContinueWith(Action<Task> continuationAction, TaskContinuationOptions continuationOptions);
参数:
continuationAction:根据在 continuationOptions 中指定的条件运行的操作。 在运行时,委托将作为一个参数传递给完成的任务。
continuationOptions:用于设置计划延续任务的时间以及延续任务的工作方式的选项。
3)TaskContinuationOptions
enum类型,用于设置计划延续任务的时间以及延续任务的工作方式的选项。 这包括条件(如System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled)和执行选项(如
System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously)。
值 |
说明 |
ContinuationOptions.None |
指定应使用默认行为。默认情况下,完成前面的任务之后将安排运行延续任务,而不考虑前面任务的最终 System.Threading.Tasks.TaskStatus。 |
ContinuationOptions.LongRunning |
指定某个任务将是运行时间长、粗粒度的操作。 它会向 System.Threading.Tasks.TaskScheduler 提示,过度订阅可能是合理的。 |
ContinuationOptions.AttachedToParent |
指定将任务附加到任务层次结构中的某个父级。 |
ContinuationOptions.DenyChildAttach |
如果尝试附有子任务到创建的任务,指定 System.InvalidOperationException 将被引发。 |
ContinuationOptions.HideScheduler |
防止环境计划程序被视为已创建任务的当前计划程序。 这意味着像 StartNew 或ContinueWith 创建任务的执行操作将被视为System.Threading.Tasks.TaskScheduler.Default当前计划程序。 |
ContinuationOptions.LazyCancellation |
在延续取消的情况下,防止延续的完成直到完成先前的任务 |
ContinuationOptions.NotOnRanToCompletion |
指定不应在延续任务前面的任务已完成运行的情况下安排延续任务。 此选项对多任务延续无效 |
ContinuationOptions.NotOnFaulted |
指定不应在延续任务前面的任务引发了未处理异常的情况下安排延续任务。 此选项对多任务延续无效 |
ContinuationOptions.OnlyOnCanceled |
指定只应在延续任务前面的任务已取消的情况下才安排延续任务。 此选项对多任务延续无效 |
ContinuationOptions.NotOnCanceled |
指定不应在延续任务前面的任务已取消的情况下安排延续任务。 此选项对多任务延续无效 |
ContinuationOptions.OnlyOnFaulted |
指定只应在延续任务前面的任务引发了未处理异常的情况下才安排延续任务。 此选项对多任务延续无效 |
ContinuationOptions.OnlyOnRanToCompletion |
指定只应在延续任务前面的任务已完成运行的情况下才安排延续任务。 此选项对多任务延续无效 |
ContinuationOptions.ExecuteSynchronously |
指定应同步执行延续任务。 指定此选项后,延续任务将在导致前面的任务转换为其最终状态的相同线程上运行。 如果在创建延续任务时已经完成前面的任务,则延续任务将在创建此延续任务的线程上运行。只应同步执行运行时间非常短的延续任务 |
ContinuationOptions.PreferFairness |
提示 System.Threading.Tasks.TaskScheduler 以一种尽可能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。 |
注意:
1)可以通过位操作组合使用多个值。
2)使用ContinuationOptions.None意味着不论前面的任务是否被取消,延续任务都会执行。
异常:
System.ObjectDisposedException:System.Threading.Tasks.Task 已被释放。
System.ArgumentNullException:continuationAction 参数为 null。
System.ArgumentOutOfRangeException:continuationOptions 参数为System.Threading.Tasks.TaskContinuationOptions 指定无效值。
3)子任务(嵌套任务):在父任务的委托中创建的 System.Threading.Tasks.Task 实例。 子任务包括两种:附加的子任务与分离的子任务
- 分离的子任务是不依赖于其父级而执行。
- 附加的子任务是使用 TaskCreationOptions.AttachedToParent 选项创建的,依赖于其父任务而执行。 对父任务使用TaskCreationOptions.DenyChildAttach来阻止子任务附加到父任务。
- 一个任务可以创建任意数量的附加的子任务和分离的子任务,这仅受系统资源限制。
- 不提倡创建附加的子任务,这样会大大增加程序设计的复杂性。
10 使用模式
1)创建任务
基本形式:
1 private void CreatTask()
2 {
3 //创建并执行任务
4 Task task = new Task(() =>
5 {
6 //具体操作
7 });
8 task.Start();
9
10 //创建并将任务加入执行计划,使用StartNew
11 Task.Factory.StartNew(() => {
12 //具体操作
13 });
14
15 //创建并将任务加入执行计划,使用Run
16 Task.Run(() =>
17 {
18 //具体操作
19 });
20
21 //安排任务
22 Task.Factory.StartNew(() =>
23 {
24 //具体操作
25 },TaskCreationOptions.PreferFairness);
26 }
创建附加的子任务:
1 private void CreateTask_Parent()
2 {
3 //附加子任务
4 var taskParent = Task.Factory.StartNew(() =>
5 {
6 //操作......
7 var child = Task.Factory.StartNew(() =>
8 {
9 //具体操作
10 }, TaskCreationOptions.AttachedToParent);
11 });
12 taskParent.Wait();
13
14
15 //阻止附加子任务
16 var taskParentZ = Task.Factory.StartNew(() =>
17 {
18 //操作......
19 var child = Task.Factory.StartNew(() =>
20 {
21 //即使设置TaskCreationOptions.AttachedToParent也无法将其附加到父任务
22 //具体操作
23 }, TaskCreationOptions.AttachedToParent);
24 }, TaskCreationOptions.DenyChildAttach);
25 taskParentZ .Wait();
26 }
2)取消任务
1 public static void CancelFromExternal_Task()
2 {
3 CancellationTokenSource cts = new CancellationTokenSource();
4
5 //其他操作...
6
7 //计算condition
8 bool condition = ...;
9 if (condition) cts.Cancel();
10 //或使用Operation2_Task(cts);
11 Operation1_Task(cts);
12 //其他操作...
13
14 }
15
16 //1 使用IsCancellationRequested属性
17 private static void Operation1_Task(CancellationTokenSource cts)
18 {
19 CancellationToken ct = cts.Token;
20 Task.Factory.StartNew(() =>
21 {
22 //其他操作...
23 //return只对当前子线程有效
24 if (ct.IsCancellationRequested)
25 { return; }
26 //其他操作...
27 },ct);
28 }
29
30 //2 使用抛异常的方式
31 private static void Operation2_Task(CancellationTokenSource cts)
32 {
33 CancellationToken ct = cts.Token;
34 Task.Factory.StartNew(() =>
35 {
36 //其他操作...
37 ct.ThrowIfCancellationRequested();
38 //其他操作...
39 }, ct);
40 }
3)等待任务完成
1 private void WaitFunc()
2 {
3 Task task = new Task(() =>
4 {
5 //具体操作
6 });
7 task.Start();
8 task.Wait();
9 }
10
11 private void WaitAllFunc()
12 {
13 Task task1 = Task.Run(() =>
14 {
15 //具体操作
16 });
17 Task task2 = Task.Run(() =>
18 {
19 //具体操作
20 });
21 //等待task1与task2,直到它们完成为止
22 Task.WaitAll(task1, task2);
23
24 //等待task1与task2,如果超过1000毫秒则返回。
25 Task.WaitAll(new Task[] { task1, task2 },1000);
26 }
4)串联多个任务
1 private void contactTasks()
2 {
3 var t1 = Task.Factory.StartNew(() =>
4 {
5 //具体操作1
6 //return 返回值;
7 });
8
9 var t2 = t1.ContinueWith((t) =>
10 {
11 //具体操作2
12 //return 返回值;
13 });
14
15 var t3 = t2.ContinueWith((t) =>
16 {
17 //具体操作3
18 });
19
20 var t4 = t1.ContinueWith((t) =>
21 {
22 //具体操作4
23 });
24
25 var t5 = t1.ContinueWith((t) =>
26 {
27 //具体操作5
28 });
29
30 Task.WaitAll(t3, t4, t5);
31 }
-----------------------------------------------------------------------------------------
转载与引用请注明出处。
转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html的更多相关文章
- 转载 .Net多线程编程—并发集合 https://www.cnblogs.com/hdwgxz/p/6258014.html
集合 1 为什么使用并发集合? 原因主要有以下几点: System.Collections和System.Collections.Generic名称空间中所提供的经典列表.集合和数组都不是线程安全的, ...
- 转载 Net多线程编程—System.Threading.Tasks.Parallel
.Net多线程编程—System.Threading.Tasks.Parallel System.Threading.Tasks.Parallel类提供了Parallel.Invoke,Paral ...
- [转载] C++ 多线程编程总结
原文: http://www.cnblogs.com/zhiranok/archive/2012/05/13/cpp_multi_thread.html 在开发C++程序时,一般在吞吐量.并发.实时性 ...
- 转载:JavaScript多线程编程简介
虽然有越来越多的网站在应用AJAX技术进行开发,但是构建一个复杂的AJAX应用仍然是一个难题.造成这些困难的主要原因是什么呢?是与服务器的异步通信问题?还是GUI程序设计问题呢?通常这两项工作都是由桌 ...
- .Net多线程编程—任务Task
1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 object AsyncState 表示在 ...
- 【操作系统作业-lab4】 linux 多线程编程和调度器
linux多线程编程 参考:https://blog.csdn.net/weibo1230123/article/details/81410241 https://blog.csdn.net/skyr ...
- java多线程编程核心技术学习-1
实现多线程的两种方式 继承Thread类,重写Thread类中的run方法 public class MyThread extends Thread{ @Override public void ru ...
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- .NET 4中的多线程编程之一:使用Task(转载)
原文地址:http://www.cnblogs.com/yinzixin/archive/2011/11/04/2235233.html .NET 4为了简化多线程编程,提供了System.Threa ...
随机推荐
- [转]ui-grid User can't select the row by clicking the select checkbox available in the respective row when enableFullRowSelection : true"
本文转自:https://github.com/angular-ui/ui-grid/issues/5239 Try this style to enable checkbox selection: ...
- spring cloud config安全
前面两篇介绍了spring cloud config服务端和客户端的简单配置,本篇介绍如何保护config server及对应config client修改. 保护config server,主要是使 ...
- VS2015企业版专业版密钥
亲测可用,有需要的可以mark一下! 专业版:HMGNV-WCYXV-X7G9W-YCX63-B98R2企业版:HM6NR-QXX7C-DFW2Y-8B82K-WTYJV
- 如何对付运行时可能为 null 的 Record Type
在 F# 中,Record Type 是无法表达 null 语义的,例如,一个 Record 变量不能够使用 null 字面量赋值,接收 nullable(这里并不是指 BCL 中的 Nullable ...
- 接触Java的15天,初步了解面向对象
面向对象的三打特征:封装 ,继承 ,多态 . 图老师给的,叫我们好好看一看 对象(object):一个杯子,一台电脑,一个人,一件衣服 等,都可以称为对象. 类:类是对象的抽象的分类:比如,人类进行 ...
- IDEA maven 项目如何上传到私服仓库
前言:idea maven 发布版本到私服(快照和正式版).我有个项目( jar 包源码),其他 maven 项目能直接引入依赖就最好了,所以必须将这个 jar 包源码发布到 maven 私服仓库里去 ...
- 动态切换 web 报表中的统计图类型
统计图在浏览器端展现时,不同的使用人员对图形的展现形式会有不同的要求,有的需要柱形图.有的想看折线图等,报表支持用户在浏览器端动态的选择统计图类型,关注乾学院,查看具体实现方法动态切换 web 报表中 ...
- React.js 新手教程
正如你能从标题猜到的,这篇文章的目标是给那些有很少编程经验的读者的.比如,像我这样的人:因为迄今为止,我才探索了编程世界6个月.所以,这将是一篇新手村教程! 你只需要拥有对 HTML 和 CSS 的理 ...
- Expect 安装 on centos7
本文演示如何在CentOS7上安装和使用Expect. 使用场景 在主机A上编写并且执行Shell脚本,Shell脚本中需要ssh到主机B上执行交互命令. 安装 在主机A上安装expect: yum ...
- C# JObject和JArray 的分享
最近在调用别人的搜索引擎接口时遇到了一种返回类型为数组的情况,如 { "result": [ //根据用户输入搜索匹配到的标题数组 "我是一条新 ...