.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)创建任务
基本形式:
private void CreatTask()
{
//创建并执行任务
Task task = new Task(() =>
{
//具体操作
});
task.Start(); //创建并将任务加入执行计划,使用StartNew
Task.Factory.StartNew(() => {
//具体操作
}); //创建并将任务加入执行计划,使用Run
Task.Run(() =>
{
//具体操作
}); //安排任务
Task.Factory.StartNew(() =>
{
//具体操作
},TaskCreationOptions.PreferFairness);
}
创建附加的子任务:
private void CreateTask_Parent()
{
//附加子任务
var taskParent = Task.Factory.StartNew(() =>
{
//操作......
var child = Task.Factory.StartNew(() =>
{
//具体操作
}, TaskCreationOptions.AttachedToParent);
});
taskParent.Wait(); //阻止附加子任务
var taskParentZ = Task.Factory.StartNew(() =>
{
//操作......
var child = Task.Factory.StartNew(() =>
{
//即使设置TaskCreationOptions.AttachedToParent也无法将其附加到父任务
//具体操作
}, TaskCreationOptions.AttachedToParent);
}, TaskCreationOptions.DenyChildAttach);
taskParentZ .Wait();
}
2)取消任务
public static void CancelFromExternal_Task()
{
CancellationTokenSource cts = new CancellationTokenSource(); //其他操作... //计算condition
bool condition = ...;
if (condition) cts.Cancel();
//或使用Operation2_Task(cts);
Operation1_Task(cts);
//其他操作... } //1 使用IsCancellationRequested属性
private static void Operation1_Task(CancellationTokenSource cts)
{
CancellationToken ct = cts.Token;
Task.Factory.StartNew(() =>
{
//其他操作...
//return只对当前子线程有效
if (ct.IsCancellationRequested)
{ return; }
//其他操作...
},ct);
} //2 使用抛异常的方式
private static void Operation2_Task(CancellationTokenSource cts)
{
CancellationToken ct = cts.Token;
Task.Factory.StartNew(() =>
{
//其他操作...
ct.ThrowIfCancellationRequested();
//其他操作...
}, ct);
}
3)等待任务完成
private void WaitFunc()
{
Task task = new Task(() =>
{
//具体操作
});
task.Start();
task.Wait();
} private void WaitAllFunc()
{
Task task1 = Task.Run(() =>
{
//具体操作
});
Task task2 = Task.Run(() =>
{
//具体操作
});
//等待task1与task2,直到它们完成为止
Task.WaitAll(task1, task2); //等待task1与task2,如果超过1000毫秒则返回。
Task.WaitAll(new Task[] { task1, task2 },);
}
4)串联多个任务
private void contactTasks()
{
var t1 = Task.Factory.StartNew(() =>
{
//具体操作1
//return 返回值;
}); var t2 = t1.ContinueWith((t) =>
{
//具体操作2
//return 返回值;
}); var t3 = t2.ContinueWith((t) =>
{
//具体操作3
}); var t4 = t1.ContinueWith((t) =>
{
//具体操作4
}); var t5 = t1.ContinueWith((t) =>
{
//具体操作5
}); Task.WaitAll(t3, t4, t5);
}
-----------------------------------------------------------------------------------------
转载与引用请注明出处。
时间仓促,水平有限,如有不当之处,欢迎指正。
.Net多线程编程—任务Task的更多相关文章
- 转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html
.Net多线程编程—任务Task 1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 ob ...
- 5天玩转C#并行和多线程编程 —— 第四天 Task进阶
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
- 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
- Scalaz(45)- concurrency :Task-函数式多线程编程核心配件
我们在上一节讨论了scalaz Future,我们说它是一个不完善的类型,最起码没有完整的异常处理机制,只能用在构建类库之类的内部环境.如果scalaz在Future类定义中增加异常处理工具的话,用户 ...
- 新手浅谈Task异步编程和Thread多线程编程
初学Task的时候上网搜索,看到很多文章的标题都是task取代thread等等相关,我也一直以为task和thread是一类,其实task是.net4.0提出的异步编程,在之前.net1.0有dele ...
- C#多线程编程(1)--线程,线程池和Task
新开了一个多线程编程系列,该系列主要讲解C#中的多线程编程. 利用多线程的目的有2个: 一是防止UI线程被耗时的程序占用,导致界面卡顿:二是能够利用多核CPU的资源,提高运行效率. 我没有进行很 ...
- 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 ...
- Task+ConcurrentQueue多线程编程
队列(Queue)代表了一个先进先出的对象集合.当您需要对各项进行先进先出的访问时,则使用队列.当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队. ConcurrentQueue< ...
随机推荐
- Android Studio配置 AndroidAnnotations——Hi_博客 Android App 开发笔记
以前用Eclicps 用习惯了现在 想学学 用Android Studio 两天的钻研终于 在我电脑上装了一个Android Studio 并完成了AndroidAnnotations 的配置. An ...
- C++对C的函数拓展
一,内联函数 1.内联函数的概念 C++中的const常量可以用来代替宏常数的定义,例如:用const int a = 10来替换# define a 10.那么C++中是否有什么解决方案来替代宏代码 ...
- 了解PHP中的Array数组和foreach
1. 了解数组 PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.详细的解释可参见:PHP.net中的Array数组 . 2.例子:一般的数组 这里,我 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- 一个表缺失索引发的CPU资源瓶颈案例
背景 近几日,公司的应用团队反应业务系统突然变慢了,之前是一直比较正常.后与业务部门沟通了解详情,得知最近生意比较好,同时也在做大的促销活动,使得业务数据处理的量出现较大的增长,最终系统在处理时出现瓶 ...
- JS继承之原型继承
许多OO语言都支持两种继承方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.如前所述,由于函数没有签名,在ECMAScript中无法实现接口继承.ECMAScript只支 ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 3.安装Clus ...
- Oracle 10g安装教程
首先下载安装文件,打开后文件结构如图所示: 安装之前请关闭Windows防火墙并断开网络. xp系统下直接双击运行(本经验以XP系统安装为例进行讲述). 如果是在win7上安装,如图:在setup文件 ...
- 【流量劫持】沉默中的狂怒 —— Cookie 大喷发
精简版:http://www.cnblogs.com/index-html/p/mitm-cookie-crack.html 前言 上一篇文章 讲解了如何借助前端技术,打造一个比 SSLStrip 更 ...
- [DeviceOne开发]-do_LinearLayout组件使用技巧
一.摘要 今天跟大家主要来介绍一下DeviceOne中的do_linearlayout这个布局,在DeviceOne开发中,do_linearlayout这个布局是相当重要. 现在给大家来总结一下. ...