Task Class
https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.task?redirectedfrom=MSDN&view=netframework-4.7.2
Task Class
定义
- 命名空间:
- System.Threading.Tasks
- Assemblies:
- System.Threading.Tasks.dll, mscorlib.dll, netstandard.dll, System.Runtime.dll
表示一个异步操作。
public class Task : IAsyncResult, IDisposable
- 继承
-
Task
- 派生
- 实现
注解
Task类的表示单个操作不会返回一个值,通常以异步方式执行。 Task 对象是一种的中心思想基于任务的异步模式首次引入.NET Framework 4 中。 因为由执行工作Task对象通常以异步方式执行线程池线程上而不是以同步方式在主应用程序线程中,可以使用Status属性,并将IsCanceled, IsCompleted,和IsFaulted属性,以确定任务的状态。 大多数情况下,lambda 表达式用于指定该任务所执行的工作量。
对于返回值的操作,您使用Task<TResult>类。
本节内容:
任务实例化示例
创建和执行任务
分离任务创建和执行
等待一个或多个任务完成
任务和区域性
调试程序开发人员
任务实例化
下面的示例创建并执行四个任务。 三个任务执行Action<T>名为的委托action
,这样便可以接受类型的自变量Object。 第四个任务执行 lambda 表达式 (Action委托),它是以内联方式定义的任务创建方法调用中。 每个任务是实例化,并以不同方式运行:
任务
t1
通过调用任务类构造函数,实例化但开始通过调用其Start()方法仅在任务后面t2
已开始。任务
t2
实例化并通过调用单个方法调用中启动TaskFactory.StartNew(Action<Object>, Object)方法。任务
t3
实例化并通过调用单个方法调用中启动Run(Action)方法。任务
t4
是以同步方式执行主线程上调用RunSynchronously()方法。
因为任务t4
以同步方式,执行其主应用程序线程上执行。 剩余的任务执行异步通常在一个或多个线程池线程上。
using System;
using System.Threading;
using System.Threading.Tasks;
class Example
{
static void Main()
{
Action<object> action = (object obj) =>
{
Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, obj,
Thread.CurrentThread.ManagedThreadId);
};
// Create a task but do not start it.
Task t1 = new Task(action, "alpha");
// Construct a started task
Task t2 = Task.Factory.StartNew(action, "beta");
// Block the main thread to demonstrate that t2 is executing
t2.Wait();
// Launch t1
t1.Start();
Console.WriteLine("t1 has been launched. (Main Thread={0})",
Thread.CurrentThread.ManagedThreadId);
// Wait for the task to finish.
t1.Wait();
// Construct a started task using Task.Run.
String taskData = "delta";
Task t3 = Task.Run( () => {Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, taskData,
Thread.CurrentThread.ManagedThreadId);
});
// Wait for the task to finish.
t3.Wait();
// Construct an unstarted task
Task t4 = new Task(action, "gamma");
// Run it synchronously
t4.RunSynchronously();
// Although the task was run synchronously, it is a good practice
// to wait for it in the event exceptions were thrown by the task.
t4.Wait();
}
}
// The example displays output like the following:
// Task=1, obj=beta, Thread=3
// t1 has been launched. (Main Thread=1)
// Task=2, obj=alpha, Thread=4
// Task=3, obj=delta, Thread=3
// Task=4, obj=gamma, Thread=1
创建和执行任务
Task 可能在不同的方式中创建实例。 最常用的方法,从开始提供.NET Framework 4.5,是调用静态Run方法。 Run方法提供了简单的方法来启动任务使用默认值,而无需其他参数。 下面的示例使用Run(Action)方法以启动循环,然后显示循环迭代数的任务:
using System;
using System.Threading.Tasks;
public class Example
{
public static async Task Main()
{
await Task.Run( () => {
// Just loop.
int ctr = 0;
for (ctr = 0; ctr <= 1000000; ctr++)
{}
Console.WriteLine("Finished {0} loop iterations",
ctr);
} );
}
}
// The example displays the following output:
// Finished 1000001 loop iterations
替代方法,并使用最常见方法启动任务.NET Framework 4,是静态TaskFactory.StartNew方法。 Task.Factory属性返回TaskFactory对象。 重载的TaskFactory.StartNew方法允许您指定要传递给任务创建选项和任务计划程序参数。 下面的示例使用TaskFactory.StartNew方法来启动任务。 它是功能上等效于上一示例中的代码。
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Task t = Task.Factory.StartNew( () => {
// Just loop.
int ctr = 0;
for (ctr = 0; ctr <= 1000000; ctr++)
{}
Console.WriteLine("Finished {0} loop iterations",
ctr);
} );
t.Wait();
}
}
// The example displays the following output:
// Finished 1000001 loop iterations
有关更完整示例,请参阅基于任务的异步编程。
分离任务创建和执行
Task类还提供了构造函数对任务进行初始化,但的未计划的执行。 出于性能原因Task.Run或TaskFactory.StartNew方法是用于创建和计划计算任务的首选的机制,但对于创建和计划必须分开的方案,可以使用的构造函数,然后调用Task.Start方法来计划在更高版本时执行的任务。
等待一个或多个任务完成
因为任务通常运行以异步方式在线程池线程上,创建并启动任务的线程将继续执行,一旦该任务已实例化。 在某些情况下,调用线程时,在主应用程序线程应用程序可能会终止之前任何任务才真正开始执行。 其他情况下,应用程序的逻辑可能需要调用线程继续执行,仅当一个或多个任务已完成执行时。 你可以同步调用线程执行异步任务和它启动通过调用Wait
方法来等待一个或多个任务完成。
若要等待完成一项任务,可以调用其Task.Wait方法。 调用Wait方法进行阻止调用线程,直到单个类实例已完成执行。
下面的示例调用无参数Wait()方法无条件地等待,直到任务完成。 该任务通过调用来模拟工作Thread.Sleep两秒钟进入睡眠状态的方法。
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static Random rand = new Random();
static void Main()
{
// Wait on a single task with no timeout specified.
Task taskA = Task.Run( () => Thread.Sleep(2000));
Console.WriteLine("taskA Status: {0}", taskA.Status);
try {
taskA.Wait();
Console.WriteLine("taskA Status: {0}", taskA.Status);
}
catch (AggregateException) {
Console.WriteLine("Exception in taskA.");
}
}
}
// The example displays output like the following:
// taskA Status: WaitingToRun
// taskA Status: RanToCompletion
可以有条件地等待任务完成。 Wait(Int32)和Wait(TimeSpan)方法阻止调用线程,直到任务完成或超时间隔结束,具体取决于第一个。 由于下面的示例将启动一个任务,休眠 2 秒,但定义的一秒的超时值,调用线程受到阻止,直到在超时到期之前, 已完成执行的任务。
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
// Wait on a single task with a timeout specified.
Task taskA = Task.Run( () => Thread.Sleep(2000));
try {
taskA.Wait(1000); // Wait for 1 second.
bool completed = taskA.IsCompleted;
Console.WriteLine("Task A completed: {0}, Status: {1}",
completed, taskA.Status);
if (! completed)
Console.WriteLine("Timed out before task A completed.");
}
catch (AggregateException) {
Console.WriteLine("Exception in taskA.");
}
}
}
// The example displays output like the following:
// Task A completed: False, Status: Running
// Timed out before task A completed.
此外可以通过调用提供的取消标记Wait(CancellationToken)和Wait(Int32, CancellationToken)方法。 如果该令牌的IsCancellationRequested属性是true
或变得true
虽然Wait执行方法,该方法将引发OperationCanceledException。
在某些情况下,你可能想要等待执行任务的一系列的第一个问题以完成,但不是任务它的护理。 为此,可以调用的重载之一Task.WaitAll方法。 以下示例创建三个任务,其中每个休眠的时间间隔确定由随机数生成器。WaitAny(Task[])方法等待第一个任务完成。 该示例然后显示所有三个任务的状态信息。
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var tasks = new Task[3];
var rnd = new Random();
for (int ctr = 0; ctr <= 2; ctr++)
tasks[ctr] = Task.Run( () => Thread.Sleep(rnd.Next(500, 3000)));
try {
int index = Task.WaitAny(tasks);
Console.WriteLine("Task #{0} completed first.\n", tasks[index].Id);
Console.WriteLine("Status of all tasks:");
foreach (var t in tasks)
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
}
catch (AggregateException) {
Console.WriteLine("An exception occurred.");
}
}
}
// The example displays output like the following:
// Task #1 completed first.
//
// Status of all tasks:
// Task #3: Running
// Task #1: RanToCompletion
// Task #4: Running
您也可以等待的一系列任务的调用以完成所有WaitAll方法。 以下示例创建十个任务、 等待十个要完成,然后显示其状态。
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
// Wait for all tasks to complete.
Task[] tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
tasks[i] = Task.Run(() => Thread.Sleep(2000));
}
try {
Task.WaitAll(tasks);
}
catch (AggregateException ae) {
Console.WriteLine("One or more exceptions occurred: ");
foreach (var ex in ae.Flatten().InnerExceptions)
Console.WriteLine(" {0}", ex.Message);
}
Console.WriteLine("Status of completed tasks:");
foreach (var t in tasks)
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
}
}
// The example displays the following output:
// Status of completed tasks:
// Task #2: RanToCompletion
// Task #1: RanToCompletion
// Task #3: RanToCompletion
// Task #4: RanToCompletion
// Task #6: RanToCompletion
// Task #5: RanToCompletion
// Task #7: RanToCompletion
// Task #8: RanToCompletion
// Task #9: RanToCompletion
// Task #10: RanToCompletion
请注意时等待一个或多个任务完成时,任何正在运行的任务中引发的异常会传播调用的线程上Wait
方法,如以下示例所示。 它将启动其中三个正常完成的 12 任务和三个哪些引发的异常。 剩余的六个任务,在开始之前将三个被取消和三个将被取消时执行它们。 在中引发的异常WaitAll方法调用并处理由try
/ catch
块。
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
// Create a cancellation token and cancel it.
var source1 = new CancellationTokenSource();
var token1 = source1.Token;
source1.Cancel();
// Create a cancellation token for later cancellation.
var source2 = new CancellationTokenSource();
var token2 = source2.Token;
// Create a series of tasks that will complete, be cancelled,
// timeout, or throw an exception.
Task[] tasks = new Task[12];
for (int i = 0; i < 12; i++)
{
switch (i % 4)
{
// Task should run to completion.
case 0:
tasks[i] = Task.Run(() => Thread.Sleep(2000));
break;
// Task should be set to canceled state.
case 1:
tasks[i] = Task.Run( () => Thread.Sleep(2000),
token1);
break;
case 2:
// Task should throw an exception.
tasks[i] = Task.Run( () => { throw new NotSupportedException(); } );
break;
case 3:
// Task should examine cancellation token.
tasks[i] = Task.Run( () => { Thread.Sleep(2000);
if (token2.IsCancellationRequested)
token2.ThrowIfCancellationRequested();
Thread.Sleep(500); }, token2);
break;
}
}
Thread.Sleep(250);
source2.Cancel();
try {
Task.WaitAll(tasks);
}
catch (AggregateException ae) {
Console.WriteLine("One or more exceptions occurred:");
foreach (var ex in ae.InnerExceptions)
Console.WriteLine(" {0}: {1}", ex.GetType().Name, ex.Message);
}
Console.WriteLine("\nStatus of tasks:");
foreach (var t in tasks) {
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
if (t.Exception != null) {
foreach (var ex in t.Exception.InnerExceptions)
Console.WriteLine(" {0}: {1}", ex.GetType().Name,
ex.Message);
}
}
}
}
// The example displays output like the following:
// One or more exceptions occurred:
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
//
// Status of tasks:
// Task #13: RanToCompletion
// Task #1: Canceled
// Task #3: Faulted
// NotSupportedException: Specified method is not supported.
// Task #8: Canceled
// Task #14: RanToCompletion
// Task #4: Canceled
// Task #6: Faulted
// NotSupportedException: Specified method is not supported.
// Task #7: Canceled
// Task #15: RanToCompletion
// Task #9: Canceled
// Task #11: Faulted
// NotSupportedException: Specified method is not supported.
// Task #12: Canceled
有关基于任务的异步操作中的异常处理的详细信息,请参阅异常处理。
任务和区域性
自定位的桌面应用程序.NET Framework 4.6,创建并调用任务的线程的区域性将成为在线程的上下文的一部分。 也就是说,无论执行该任务时的当前区域性,该任务的当前区域性是线程的调用线程的区域性。 对于面向版本之前的.NET Framework 的应用, .NET Framework 4.6,任务的区域性是执行该任务时的线程的区域性。 有关详细信息,请参阅中的"区域性和基于任务的异步操作"部分CultureInfo主题。
备注
应用商店应用程序按照中设置和获取默认区域性的 Windows 运行时。
调试程序开发人员
对于开发人员实现自定义调试器,多个内部和私有成员的任务可能很有用 (这些可能会更改发行版本)。 m_taskId
字段用作后备存储Id属性,但是访问此字段直接从调试器可能会通过属性的 getter 方法访问相同的值比效率更高 (s_taskIdCounter
计数器是用于检索任务的下一个可用 ID)。 同样,m_stateFlags
字段存储的信息还可通过访问任务信息的当前生命周期阶段Status属性。 m_action
字段存储对任务的委托的引用和m_stateObject
字段存储由开发人员传递给任务的异步状态。 最后,对于分析堆栈帧的调试器InternalWait
方法提供一项任务时进入一个等待操作的潜在标记。
构造函数
Task(Action) |
使用指定的操作初始化新的 Task。 |
Task(Action, CancellationToken) |
使用指定的操作和 Task 初始化新的 CancellationToken。 |
Task(Action, CancellationToken, TaskCreationOptions) |
使用指定的操作和创建选项初始化新的 Task。 |
Task(Action, TaskCreationOptions) |
使用指定的操作和创建选项初始化新的 Task。 |
Task(Action<Object>, Object) |
使用指定的操作和状态初始化新的 Task。 |
Task(Action<Object>, Object, CancellationToken) |
使用指定的操作、状态和选项初始化新的 Task。 |
Task(Action<Object>, Object, CancellationToken, TaskCreationOptions) |
使用指定的操作、状态和选项初始化新的 Task。 |
Task(Action<Object>, Object, TaskCreationOptions) |
使用指定的操作、状态和选项初始化新的 Task。 |
属性
AsyncState |
获取在创建 Task 时提供的状态对象,如果未提供,则为 null。 |
CompletedTask |
获取一个已成功完成的任务。 |
CreationOptions |
获取用于创建此任务的 TaskCreationOptions。 |
CurrentId |
返回当前正在执行 Task 的 ID。 |
Exception |
获取导致 AggregateException 提前结束的 Task。 如果 Task 成功完成或尚未引发任何异常,这将返回 |
Factory |
提供对用于创建 Task 和 Task<TResult> 的工厂方法的访问。 |
Id |
获取此 Task 实例的 ID。 |
IsCanceled |
获取此 Task 实例是否由于被取消的原因而已完成执行。 |
IsCompleted |
获取此 Task 是否已完成。 |
IsFaulted |
获取 Task 是否由于未经处理异常的原因而完成。 |
Status |
获取此任务的 TaskStatus。 |
方法
显式界面实现
IAsyncResult.AsyncWaitHandle |
获取可用于等待任务完成的 WaitHandle。 |
IAsyncResult.CompletedSynchronously |
获取操作是否已同步完成的指示。 |
适用于
.NET Core
.NET Framework
.NET Standard
Xamarin.Android
Xamarin.iOS
Xamarin.Mac
线程安全性
所有成员Task,除Dispose()、 是线程安全的可从多个线程同时使用。
另请参阅
- Task<TResult>
- 任务并行库 (TPL) Task Parallel Library (TPL)
- 基于任务的异步编程 Task-based Asynchronous Programming
- 使用.NET Framework 进行并行编程示例 Samples for Parallel Programming with the .NET Framework
Task Class的更多相关文章
- Concepts:Request 和 Task
当SQL Server Engine 接收到Session发出的Request时,SQL Server OS将Request和Task绑定,并为Task分配一个Workder.在TSQL Query执 ...
- .Net多线程编程—任务Task
1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 object AsyncState 表示在 ...
- nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)
本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...
- windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)
本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...
- Openstack Periodic Task
Openstack Periodic Task 周期性任务在各个模块的manager.py(computer,scheduler,cell,network)中添加. 添加方法:在模块manager类实 ...
- MapReduce剖析笔记之三:Job的Map/Reduce Task初始化
上一节分析了Job由JobClient提交到JobTracker的流程,利用RPC机制,JobTracker接收到Job ID和Job所在HDFS的目录,够早了JobInProgress对象,丢入队列 ...
- [Java定时器]用Spring Task实现一个简单的定时器.
今天做一个项目的的时候需要用到定时器功能.具体需求是: 每个月一号触发一次某个类中的方法去拉取别人的接口获取上一个月份车险过期的用户.如若转载请附上原文链接:http://www.cnblogs.co ...
- 定时管理器框架-Task.MainForm
入住博客园4年多了,一直都是看别人的博客,学习别人的知识,为各个默默无私贡献自己技术总结的朋友们顶一个:这几天突然觉得是时候加入该队列中,贡献出自己微弱的力量,努力做到每个月有不同学习总结,知识学习的 ...
- Task三个列子的分享
这次要分享的是C#Task任务的几个列子,感觉最实用的是封装的分页任务执行方法,这个方法步奏也是目前在我工作中执行多任务常用的,不知道各位也有这用的情况,那么开始吧. 1.顺序任务执行 //顺序任务执 ...
- webapi+Task并行请求不同接口实例
标题的名称定义不知道是否准确,不过我想表达的意思就是使用Task特性来同时请求多个不同的接口,然后合并数据:我想这种场景的开发对于对接过其他公司接口的人不会陌生,本人也是列属于之内,更多的是使用最原始 ...
随机推荐
- Spring Boot 揭秘与实战(二) 数据存储篇 - 声明式事务管理
文章目录 1. 声明式事务 2. Spring Boot默认集成事务 3. 实战演练4. 源代码 3.1. 实体对象 3.2. DAO 相关 3.3. Service 相关 3.4. 测试,测试 本文 ...
- 【计算机视觉】seetaFace
class impl class FaceDetection::Impl { public: Impl() : detector_(new seeta::fd::FuStDetector()), sl ...
- 2017 ACM-ICPC EC-Final ShangHai 东亚洲大陆-上海
比赛链接:传送门 Gym 101775A Chat Group(签到:待补) Gym 101775B Scapegoat(待补) Gym 101775C Traffic Light(贪心+思维) 思路 ...
- Blender节点笔记
Blender节点笔记实现复杂材质,纹理的更直观的方式就是使用节点功能. 每个节点左边作为输入,右边作为输出.节点之间通过传递值影响后者.传递的值为(Scalars,Vectors)标量与矢量.二维矢 ...
- emacs安装
1.我选用的是Ubuntu16.04. 2.Ubuntu安装好之后不能直接sudo apt-get install emacs,因为Ubuntu的源默认是emacs24,最好是用最新的emacs25, ...
- Go Example--接口
package main import ( "math" "fmt" ) type geometry interface { area() float64 pe ...
- 鸟哥的linux私房菜第4版--自学笔记
-----------------------------------第一章 intel芯片架构 PS:升级电脑还得看看主板是不是适合CPU,主板适合CPU的类型是有限的PS: 现在已经没有北桥了,已 ...
- zabbix监控mysql最简单的方法
该实验基于我的上一篇文章监控第一台主机的基础上 首先,因为水平有限,我选择直接关闭了防火墙和SELinux. 环境: 两台centos7,服务器端IP是192.168.200.128(以下简称主机), ...
- day 57 jQuery的补充
.data() 在匹配的元素集合中的所有元素上存储任意相关数据或返回匹配的元素集合中的第一个元素的给定名称的数据存储的值. .data(key, value): 描述:在匹配的元素上存储任意相关数据. ...
- Singer 学习七 运行&&开发taps、targets (二 targets 运行说明)
接上文: Singer 学习六 运行&&开发taps.targets (一 taps 运行说明) 说明target 需要tap 进行配合运行,所以需要了解tap 的使用 运行targe ...