命名空间:
System.Threading.Tasks
程序集:
mscorlib.dll, netstandard.dll
表示一个异步操作。
继承
Object
Task
派生
System.Threading.Tasks.Task
实现
IAsyncResult
Task类表示不返回值并且通常以异步方式执行的单个操作。 Task 对象是在 .NET Framework 4 中首次引入的 基于任务的异步模式 的中心组件之一。 由于对象执行的工作 Task 通常在线程池线程上异步执行,而不是在主应用程序线程上同步执行,因此可以使用 Status 属性以及 IsCanceled 、 IsCompleted 和 IsFaulted 属性来确定任务的状态。 通常,lambda 表达式用于指定任务要执行的工作。
对于返回值的操作,请使用 Task
本部分内容:
任务实例化示例
创建和执行任务
分离任务创建和执行
正在等待一个或多个任务完成
任务和区域性
对于调试器开发人员
下面的示例创建并执行四个任务。 三个任务执行 Actionaction
,该委托接受类型的参数 Object 。 第四个任务执行 lambda 表达式 (Action 委托) ,该委托在对任务创建方法的调用中以内联方式定义。 每个任务实例化并以不同的方式运行:
任务 t1
是通过调用任务类构造函数来实例化的,但 Start() 只有在任务启动之后才会通过调用其方法来启动 t2
。
t2
通过调用方法,在单个方法调用中实例化和启动任务 TaskFactory.StartNew(Action
t3
通过调用方法,在单个方法调用中实例化和启动任务 Run(Action) 。
t4
通过调用方法,在主线程上同步执行任务 RunSynchronously() 。
由于任务以 t4
同步方式执行,因此它在主应用程序线程上执行。 其余任务通常在一个或多个线程池线程上异步执行。
C#复制
using System;
using System.Threading;
using System.Threading.Tasks;
class Example
{
static void Main()
{
Action
Task 可以通过多种方式创建实例。 从 .NET Framework 4.5 开始,最常见的方法是调用静态 Run 方法。 Run方法提供了一种简单的方法来使用默认值启动任务,而无需其他参数。 下面的示例使用 Run(Action) 方法来启动任务,该任务将循环,并显示循环迭代次数:
C#复制
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 方法来启动任务。 它在功能上等效于上一示例中的代码。
C#复制
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 方法来模拟两秒钟的工作。
C#复制
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) 方法会阻止调用线程,直到任务完成或超时间隔(以先达到者为准)为止。 由于下面的示例将启动一个睡眠时间为两秒的任务,但定义了一秒的超时值,因此调用线程将会阻塞,直到超时过期以及任务已完成执行。
C#复制
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.WaitAny 。 下面的示例创建三个任务,每个任务都休眠由随机数生成器确定的间隔。 WaitAny(Task[])方法等待第一个任务完成。 然后,该示例显示所有三个任务的状态信息。
C#复制
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 。 下面的示例创建了十个任务,等待所有十个任务完成,然后显示其状态。
C#复制
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
块处理。
C#复制
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 4.6 之前的 .NET Framework 版本的应用,任务的区域性是执行任务的线程的区域性。 有关详细信息,请参阅主题中的 "区域性和基于任务的异步操作" 一节 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 | 使用指定的操作和状态初始化新的 Task。 |
Task(Action | 使用指定的操作、状态和选项初始化新的 Task。 |
Task(Action | 使用指定的操作、状态和选项初始化新的 Task。 |
Task(Action | 使用指定的操作、状态和选项初始化新的 Task。 |
AsyncState | 获取在创建 Task 时提供的状态对象,如果未提供,则为 null。 |
CompletedTask | 获取一个已成功完成的任务。 |
CreationOptions | 获取用于创建此任务的 TaskCreationOptions。 |
CurrentId | 返回当前正在执行 Task 的 ID。 |
Exception | 获取导致 AggregateException 提前结束的 Task。 如果 Task 成功完成或尚未引发任何异常,这将返回 |
Factory | 提供对用于创建和配置 Task 和 Task |
Id | 获取此 Task 实例的 ID。 |
IsCanceled | 获取此 Task 实例是否由于被取消的原因而已完成执行。 |
IsCompleted | 获取一个值,它表示是否已完成任务。 |
IsCompletedSuccessfully | 了解任务是否运行到完成。 |
IsFaulted | 获取 Task 是否由于未经处理异常的原因而完成。 |
Status | 获取此任务的 TaskStatus。 |
ConfigureAwait(Boolean) | 配置用于等待此 Task的 awaiter。 |
ContinueWith(Action |
创建一个在目标 Task 完成时接收调用方提供的状态信息并执行的延续任务。 |
ContinueWith(Action |
创建一个在目标 Task 完成时接收调用方提供的状态信息和取消标记,并以异步方式执行的延续任务。 |
ContinueWith(Action |
创建一个在目标 Task 完成时接收调用方提供的状态信息和取消标记并执行的延续任务。 延续任务根据一组指定的条件执行,并使用指定的计划程序。 |
ContinueWith(Action |
创建一个在目标 Task 完成时接收调用方提供的状态信息并执行的延续任务。 延续任务根据一组指定的条件执行。 |
ContinueWith(Action |
创建一个在目标 Task 完成时接收调用方提供的状态信息并以异步方式执行的延续任务。 延续任务使用指定计划程序。 |
ContinueWith(Action |
创建一个在目标 Task 完成时异步执行的延续任务。 |
ContinueWith(Action |
创建一个在目标 Task 完成时可接收取消标记并以异步方式执行的延续任务。 |
ContinueWith(Action |
创建一个在目标任务完成时按照指定的 TaskContinuationOptions 执行的延续任务。 延续任务会收到一个取消标记,并使用指定的计划程序。 |
ContinueWith(Action |
创建一个在目标任务完成时按照指定的 TaskContinuationOptions 执行的延续任务。 |
ContinueWith(Action |
创建一个在目标 Task 完成时异步执行的延续任务。 延续任务使用指定计划程序。 |
ContinueWith |
创建一个在目标 Task 完成并返回一个值时接收调用方提供的状态信息并以异步方式执行的延续任务。 |
ContinueWith |
创建一个在目标 Task 完成时异步执行并返回一个值的延续任务。 延续任务接收调用方提供的状态信息和取消标记。 |
ContinueWith |
创建一个在目标 Task 完成并返回一个值时根据指定的任务延续选项执行的延续任务。 延续任务接收调用方提供的状态信息和取消标记,并使用指定的计划程序。 |
ContinueWith |
创建一个在目标 Task 完成时根据指定的任务延续选项执行的延续任务。 延续任务接收调用方提供的状态信息。 |
ContinueWith |
创建一个在目标 Task 完成时异步执行的延续任务。 延续任务接收调用方提供的状态信息,并使用指定的计划程序。 |
ContinueWith |
创建一个在目标 Task |
ContinueWith |
创建一个在目标 Task 完成时异步执行并返回一个值的延续任务。 延续任务收到取消标记。 |
ContinueWith |
创建一个按照指定延续任务选项执行并返回一个值的延续任务。 延续任务被传入一个取消标记,并使用指定的计划程序。 |
ContinueWith |
创建一个按照指定延续任务选项执行并返回一个值的延续任务。 |
ContinueWith |
创建一个在目标 Task 完成时异步执行并返回一个值的延续任务。 延续任务使用指定计划程序。 |
Delay(Int32) | 创建一个在指定的毫秒数后完成的任务。 |
Delay(Int32, CancellationToken) | 创建一个在指定的毫秒数后完成的可取消任务。 |
Delay(TimeSpan) | 创建一个在指定的时间间隔后完成的任务。 |
Delay(TimeSpan, CancellationToken) | 创建一个在指定的时间间隔后完成的可取消任务。 |
Dispose() | 释放 Task 类的当前实例所使用的所有资源。 |
Dispose(Boolean) | 释放 Task,同时释放其所有非托管资源。 |
Equals(Object) | 确定指定对象是否等于当前对象。 (继承自 Object) |
FromCanceled(CancellationToken) | 创建 Task,它因指定的取消标记进行的取消操作而完成。 |
FromCanceled |
创建 Task |
FromException(Exception) | 创建 Task,它在完成后出现指定的异常。 |
FromException |
创建 Task |
FromResult |
创建指定结果的、成功完成的 Task |
GetAwaiter() | 获取用于等待此 Task 的 awaiter。 |
GetHashCode() | 作为默认哈希函数。 (继承自 Object) |
GetType() | 获取当前实例的 Type。 (继承自 Object) |
MemberwiseClone() | 创建当前 Object 的浅表副本。 (继承自 Object) |
Run(Action) | 将在线程池上运行的指定工作排队,并返回代表该工作的 Task 对象。 |
Run(Action, CancellationToken) | 将在线程池上运行的指定工作排队,并返回代表该工作的 Task 对象。 可使用取消标记来取消工作(如果尚未启动)。 |
Run(Func |
将在线程池上运行的指定工作排队,并返回 |
Run(Func |
将在线程池上运行的指定工作排队,并返回 |
Run |
将指定的工作排成队列在线程池上运行,并返回由 |
Run |
将指定的工作排成队列在线程池上运行,并返回由 |
Run |
将在线程池上运行的指定工作排队,并返回代表该工作的 Task |
Run |
将在线程池上运行的指定工作排队,并返回代表该工作的 |
RunSynchronously() | 对当前的 Task 同步运行 TaskScheduler。 |
RunSynchronously(TaskScheduler) | 对提供的 Task 同步运行 TaskScheduler。 |
Start() | 启动 Task,并将它安排到当前的 TaskScheduler 中执行。 |
Start(TaskScheduler) | 启动 Task,并将它安排到指定的 TaskScheduler 中执行。 |
ToString() | 返回表示当前对象的字符串。 (继承自 Object) |
Wait() | 等待 Task 完成执行过程。 |
Wait(CancellationToken) | 等待 Task 完成执行过程。 如果在任务完成之前取消标记已取消,等待将终止。 |
Wait(Int32) | 等待 Task 在指定的毫秒数内完成执行。 |
Wait(Int32, CancellationToken) | 等待 Task 完成执行过程。 如果在任务完成之前超时间隔结束或取消标记已取消,等待将终止。 |
Wait(TimeSpan) | 等待 Task 在指定的时间间隔内完成执行。 |
WaitAll(Task[]) | 等待提供的所有 Task 对象完成执行过程。 |
WaitAll(Task[], CancellationToken) | 等待提供的所有 Task 对象完成执行过程(除非取消等待)。 |
WaitAll(Task[], Int32) | 等待所有提供的 Task 在指定的毫秒数内完成执行。 |
WaitAll(Task[], Int32, CancellationToken) | 等待提供的所有 Task 对象在指定的毫秒数内完成执行,或等到取消等待。 |
WaitAll(Task[], TimeSpan) | 等待所有提供的可取消 Task 对象在指定的时间间隔内完成执行。 |
WaitAny(Task[]) | 等待提供的任一 Task 对象完成执行过程。 |
WaitAny(Task[], CancellationToken) | 等待提供的任何 Task 对象完成执行过程(除非取消等待)。 |
WaitAny(Task[], Int32) | 等待任何提供的 Task 对象在指定的毫秒数内完成执行。 |
WaitAny(Task[], Int32, CancellationToken) | 等待提供的任何 Task 对象在指定的毫秒数内完成执行,或等到取消标记取消。 |
WaitAny(Task[], TimeSpan) | 等待任何提供的 Task 对象在指定的时间间隔内完成执行。 |
WhenAll(IEnumerable |
创建一个任务,该任务将在可枚举集合中的所有 Task 对象都已完成时完成。 |
WhenAll(Task[]) | 创建一个任务,该任务将在数组中的所有 Task 对象都已完成时完成。 |
WhenAll |
创建一个任务,该任务将在可枚举集合中的所有 Task |
WhenAll |
创建一个任务,该任务将在数组中的所有 Task |
WhenAny(IEnumerable |
任何提供的任务已完成时,创建将完成的任务。 |
WhenAny(Task, Task) | 提供的任一任务完成时,创建将完成的任务。 |
WhenAny(Task[]) | 任何提供的任务已完成时,创建将完成的任务。 |
WhenAny |
任何提供的任务已完成时,创建将完成的任务。 |
WhenAny |
提供的任一任务完成时,创建将完成的任务。 |
WhenAny |
任何提供的任务已完成时,创建将完成的任务。 |
Yield() | 创建异步产生当前上下文的等待任务。 |
IAsyncResult.AsyncWaitHandle | 获取可用于等待任务完成的 WaitHandle。 |
IAsyncResult.CompletedSynchronously | 获取操作是否已同步完成的指示。 |
DispatcherOperationWait(Task) | 无限期等待完成基础 DispatcherOperation。 |
DispatcherOperationWait(Task, TimeSpan) | 等待基础 DispatcherOperation 完成,直到达到指定的所需时间。 |
IsDispatcherOperationTask(Task) | 返回一个值,该值指示此 Task 是否与 DispatcherOperation 相关。 |
产品 | 版本 |
---|---|
.NET | Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6 |
.NET Framework | 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8 |
.NET Standard | 1.0, 1.1, 1.2, 1.3, 1.4, 1.6, 2.0, 2.1 |
UWP | 10.0 |
Xamarin.iOS | 10.8 |
Xamarin.Mac | 3.0 |
除之外的所有成员 Task Dispose() 都是线程安全的,可同时从多个线程使用。