.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< ...
随机推荐
- 使用TSQL查询和更新 JSON 数据
JSON是一个非常流行的,用于数据交换的文本数据(textual data)格式,主要用于Web和移动应用程序中.JSON 使用“键/值对”(Key:Value pair)存储数据,能够表示嵌套键值对 ...
- mobx @computed的解读
写在前面:我一开始看不懂官网的@computed的作用,因为即使我把@computed去掉,依然能正确的report,然后我百度谷歌都找不到答案,下面都是我自己的理解,如果是有问题的,不对的,请务必留 ...
- boost强分类器的实现
boost.cpp文件下: bool CvCascadeBoost::train( const CvFeatureEvaluator* _featureEvaluator, int _numSampl ...
- 在ASP.NET Core中使用百度在线编辑器UEditor
在ASP.NET Core中使用百度在线编辑器UEditor 0x00 起因 最近需要一个在线编辑器,之前听人说过百度的UEditor不错,去官网下了一个.不过服务端只有ASP.NET版的,如果是为了 ...
- JavaScript性能优化
如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍J ...
- 深入理解MySql子查询IN的执行和优化
IN为什么慢? 在应用程序中使用子查询后,SQL语句的查询性能变得非常糟糕.例如: SELECT driver_id FROM driver where driver_id in (SELECT dr ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(71)-微信公众平台开发-公众号管理
系列目录 思维导图 下面我们来看一个思维导图,这样就可以更快了解所需要的功能: 上一节我们利用了一个简单的代码例子,完成了与微信公众号的对话(给公众号发一条信息,并得到回复) 这一节将讲解公众号如何设 ...
- spring源码分析之@ImportSelector、@Import、ImportResource工作原理分析
1. @importSelector定义: /** * Interface to be implemented by types that determine which @{@link Config ...
- css知多少之绝对定位小记
一.position定位常见属性 对于属性position来说,属性值有static/relative/absolute/fixed/inherit以下只对绝对定位position:absolute详 ...
- 关于BAPI_PATIENT_CREATE(病患主数据创建)
第一次使用BAPI,遇到几个问题.现总结如下. CALL FUNCTION 'BAPI_PATIENT_CREATE' EXPORTING client = * INSTITUTION = '*' * ...