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的更多相关文章

  1. 转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html

    .Net多线程编程—任务Task   1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 ob ...

  2. 5天玩转C#并行和多线程编程 —— 第四天 Task进阶

    5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...

  3. 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task

    5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...

  4. Scalaz(45)- concurrency :Task-函数式多线程编程核心配件

    我们在上一节讨论了scalaz Future,我们说它是一个不完善的类型,最起码没有完整的异常处理机制,只能用在构建类库之类的内部环境.如果scalaz在Future类定义中增加异常处理工具的话,用户 ...

  5. 新手浅谈Task异步编程和Thread多线程编程

    初学Task的时候上网搜索,看到很多文章的标题都是task取代thread等等相关,我也一直以为task和thread是一类,其实task是.net4.0提出的异步编程,在之前.net1.0有dele ...

  6. C#多线程编程(1)--线程,线程池和Task

    新开了一个多线程编程系列,该系列主要讲解C#中的多线程编程.    利用多线程的目的有2个: 一是防止UI线程被耗时的程序占用,导致界面卡顿:二是能够利用多核CPU的资源,提高运行效率. 我没有进行很 ...

  7. 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 ...

  8. .NET 4中的多线程编程之一:使用Task(转载)

    原文地址:http://www.cnblogs.com/yinzixin/archive/2011/11/04/2235233.html .NET 4为了简化多线程编程,提供了System.Threa ...

  9. Task+ConcurrentQueue多线程编程

    队列(Queue)代表了一个先进先出的对象集合.当您需要对各项进行先进先出的访问时,则使用队列.当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队. ConcurrentQueue< ...

随机推荐

  1. 【解决方案】Myeclipse 10 安装 GIT 插件 集成 步骤 图解

    工程开发中,往往要使用到集成GIT ,那么下面说说插件安装步骤 PS:以Myeclipse 10 为例,讲解集成安装步骤. ----------------------main------------ ...

  2. Android性能优化之利用Rxlifecycle解决RxJava内存泄漏

    前言: 其实RxJava引起的内存泄漏是我无意中发现了,本来是想了解Retrofit与RxJava相结合中是如何通过适配器模式解决的,结果却发现了RxJava是会引起内存泄漏的,所有想着查找一下资料学 ...

  3. 第一个移动前端开源项目-dailog

    你还在为手机上没有忙碌光标而发愁吗?你还在抱怨弹出框组件要依赖zepto/jqery吗?你还在纠结是否要自己写一套还是去网上寻找成现成的UI组件吗?YouA为你轻松解决所有烦恼.YouA是我为移动前端 ...

  4. IE8/9 本地预览上传图片

    本地预览的意思是,在选择图片之后先不上传到服务器,而是由一个<img>标签来预览本地的图片,非 IE8/9 浏览器可以从<input type="file"/&g ...

  5. .Net Core上用于代替System.Drawing的类库

    目前.Net Core上没有System.Drawing这个类库,想要在.Net Core上处理图片得另辟蹊径. 微软给出了将来取代System.Drawing的方案,偏向于使用一个单独的服务端进行各 ...

  6. npm 使用小结

    本文内容基于 npm 4.0.5 概述 npm (node package manager),即 node 包管理器.这里的 node 包就是指各种 javascript 库. npm 是随同 Nod ...

  7. 用Kotlin实现Android定制视图(KAD 06)

    作者:Antonio Leiva 时间:Dec 27, 2016 原文链接:https://antonioleiva.com/custom-views-android-kotlin/ 在我们阅读有关c ...

  8. Linux基础介绍【第七篇】

    linux用户分类 超级用户:UID=0,root 普通用户:UID 500起,由超级用户或具有超级用户权限的用户创建的用户. 虚拟用户:UID 1-499,为了满足文件或服务启动的需要而存在,一般都 ...

  9. mono-3.4.0 源码安装时出现的问题 [do-install] Error 2 [install-pcl-targets] Error 1 解决方法

    Mono 3.4修复了很多bug,继续加强稳定性和性能(其实Mono 3.2.8 已经很稳定,性能也很好了),但是从http://download.mono-project.com/sources/m ...

  10. Web前端温故知新-CSS基础

    一.CSS定义与编写CSS 1.1 CSS的定义 全名:Cascading Style Sheets -> 层叠样式表 定义:CSS成为层叠样式表,它主要用于设置HTML页面中的文本内容(字体. ...