Task 类

定义

表示异步操作。

public ref class Task : IAsyncResult
public ref class Task : IAsyncResult, IDisposable
public class Task : IAsyncResult
public class Task : IAsyncResult, IDisposable
type Task = class
    interface IAsyncResult
type Task = class
    interface IAsyncResult
    interface IDisposable
Public Class Task
Implements IAsyncResult
Public Class Task
Implements IAsyncResult, IDisposable
继承
Task
派生
实现

注解

Task 类表示不返回值且通常以异步方式执行的单个作。 Task 对象是 基于任务的异步模式的中心组件之一。 由于对象执行的工作通常以异步方式在线程池线程上执行,而不是在主应用程序线程上同步执行Task,因此可以使用Status属性IsCanceledIsCompleted以及IsFaulted属性来确定任务的状态。 通常,lambda 表达式用于指定任务要执行的工作。

对于返回值的操作,使用Task<TResult>类。

任务实例化

以下示例创建并执行四个任务。 三个任务执行名为 Action<T>action 委托,该委托接受一个类型为 Object 的参数。 第四个任务执行在调用任务创建方法时内联定义的 lambda 表达式(即 Action 委托)。 每个任务都以不同的方式实例化并运行:

  • 任务通过调用 Task 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
open System.Threading
open System.Threading.Tasks

let action =
    fun (obj: obj) -> printfn $"Task={Task.CurrentId}, obj={obj}, Thread={Thread.CurrentThread.ManagedThreadId}"

// Create a task but do not start it.
let t1 = new Task(action, "alpha")

// Construct a started task
let t2 = Task.Factory.StartNew(action, "beta")
// Block the main thread to demonstrate that t2 is executing
t2.Wait()

// Launch t1
t1.Start()
printfn $"t1 has been launched. (Main Thread={Thread.CurrentThread.ManagedThreadId})"
// Wait for the task to finish.
t1.Wait()

// Construct a started task using Task.Run.
let taskData = "delta"

let t3 =
    Task.Run(fun () -> printfn $"Task={Task.CurrentId}, obj={taskData}, Thread={Thread.CurrentThread.ManagedThreadId}")
// Wait for the task to finish.
t3.Wait()

// Construct an unstarted task
let 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
Imports System.Threading
Imports System.Threading.Tasks

Module Example2
    Public Sub Main()
        Dim action As Action(Of Object) =
              Sub(obj As Object)
                  Console.WriteLine("Task={0}, obj={1}, Thread={2}",
                 Task.CurrentId, obj,
                 Thread.CurrentThread.ManagedThreadId)
              End Sub

        ' Construct an unstarted task
        Dim t1 As New Task(action, "alpha")

        ' Construct a started task
        Dim t2 As Task = 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.
        Dim taskData As String = "delta"
        Dim t3 As Task = Task.Run(Sub()
                                      Console.WriteLine("Task={0}, obj={1}, Thread={2}",
                                     Task.CurrentId, taskData,
                                     Thread.CurrentThread.ManagedThreadId)
                                  End Sub)
        ' Wait for the task to finish.
        t3.Wait()

        ' Construct an unstarted task
        Dim t4 As 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()
    End Sub
End Module
' 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=3
'       Task=3, obj=delta, Thread=3
'       Task=4, obj=gamma, Thread=1

创建和执行任务

可以通过多种方式创建 Task 实例。 最常见的方法是调用静态 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
open System.Threading.Tasks

let main =
    task {
        do!
            Task.Run(fun () ->
                for i = 0 to 1000000 do
                    printfn $"Finished {i} loop iterations")
    }

main.Wait()

// The example displays the following output:
//        Finished 1000001 loop iterations
Imports System.Threading.Tasks

Module Example1
    Public Sub Main()
        Dim t As Task = Task.Run(Sub()
                                     ' Just loop.
                                     Dim ctr As Integer = 0
                                     For ctr = 0 To 1000000
                                     Next
                                     Console.WriteLine("Finished {0} loop iterations",
                                                    ctr)
                                 End Sub)
        t.Wait()
    End Sub
End Module
' The example displays the following output:
'       Finished 1000001 loop iterations

另一种方法是静态 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
open System.Threading.Tasks

let t =
    Task.Factory.StartNew(fun () ->
        // Just loop.
        for i = 0 to 1000000 do
            printfn $"Finished {i} loop iterations")

t.Wait()


// The example displays the following output:
//        Finished 1000001 loop iterations
Imports System.Threading.Tasks

Module Example3
    Public Sub Main()
        Dim t As Task = Task.Factory.StartNew(Sub()
                                                  ' Just loop.
                                                  Dim ctr As Integer = 0
                                                  For ctr = 0 To 1000000
                                                  Next
                                                  Console.WriteLine("Finished {0} loop iterations",
                                                    ctr)
                                              End Sub)
        t.Wait()
    End Sub
End Module
' The example displays the following output:
'       Finished 1000001 loop iterations

有关更完整的示例,请参阅 基于任务的异步编程

单独的任务创建和执行

Task 类还提供用于初始化任务的构造函数,但不计划任务执行。 出于性能原因, Task.RunTaskFactory.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
open System
open System.Threading
open System.Threading.Tasks

let rand = Random()

// Wait on a single task with no timeout specified.
let taskA = Task.Run(fun () -> Thread.Sleep 2000)
printfn $"taskA Status: {taskA.Status}"
try 
    taskA.Wait()
    printfn $"taskA Status: {taskA.Status}"

with :? AggregateException ->
    printfn "Exception in taskA."

// The example displays output like the following:
//     taskA Status: WaitingToRun
//     taskA Status: RanToCompletion
Imports System.Threading
Imports System.Threading.Tasks

Module Example4
    Public Sub Main()
        ' Wait on a single task with no timeout specified.
        Dim taskA = Task.Run(Sub() Thread.Sleep(2000))
        Console.WriteLine("taskA Status: {0}", taskA.Status)
        Try
            taskA.Wait()
            Console.WriteLine("taskA Status: {0}", taskA.Status)
        Catch e As AggregateException
            Console.WriteLine("Exception in taskA.")
        End Try
    End Sub
End Module
' The example displays output like the following:
'     taskA Status: WaitingToRun
'     taskA Status: RanToCompletion

还可以有条件地等待任务完成。 Wait(Int32)Wait(TimeSpan) 方法会阻止调用线程,直到任务完成或超时间隔过去,以先到者为准。 由于以下示例启动了一个任务,该任务会休眠两秒,但设置了一个一秒的超时值,调用线程会阻塞,直至超时到期,而此时任务尚未执行完毕。

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.
open System
open System.Threading
open System.Threading.Tasks

// Wait on a single task with a timeout specified.
let taskA = Task.Run(fun () -> Thread.Sleep 2000)

try
    taskA.Wait 1000 |> ignore // Wait for 1 second.
    let completed = taskA.IsCompleted
    printfn $"Task A completed: {completed}, Status: {taskA.Status}"

    if not completed then
        printfn "Timed out before task A completed."

with :? AggregateException ->
    printfn "Exception in taskA."


// The example displays output like the following:
//     Task A completed: False, Status: Running
//     Timed out before task A completed.
Imports System.Threading
Imports System.Threading.Tasks

Module Example5
    Public Sub Main()
        ' Wait on a single task with a timeout specified.
        Dim taskA As Task = Task.Run(Sub() Thread.Sleep(2000))
        Try
            taskA.Wait(1000)        ' Wait for 1 second.
            Dim completed As Boolean = taskA.IsCompleted
            Console.WriteLine("Task.Completed: {0}, Status: {1}",
                           completed, taskA.Status)
            If Not completed Then
                Console.WriteLine("Timed out before task A completed.")
            End If
        Catch e As AggregateException
            Console.WriteLine("Exception in taskA.")
        End Try
    End Sub
End Module
' The example displays the following output:
'     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[]) 方法等待第一个任务完成。 然后,该示例显示有关所有三个任务的状态的信息。

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
open System
open System.Threading
open System.Threading.Tasks

let rnd = new Random()

let tasks =
    [| for _ = 0 to 2 do
           Task.Run(fun () -> rnd.Next(500, 3000) |> Thread.Sleep) |]

try
    let index = Task.WaitAny tasks
    printfn $"Task #{tasks[index].Id} completed first.\n"
    printfn "Status of all tasks:"

    for t in tasks do
        printfn $"   Task #{t.Id}: {t.Status}"

with :? AggregateException ->
    printfn "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
Imports System.Threading
Imports System.Threading.Tasks

Module Example8
    Public Sub Main()
        Dim tasks(2) As Task
        Dim rnd As New Random()
        For ctr As Integer = 0 To 2
            tasks(ctr) = Task.Run(Sub() Thread.Sleep(rnd.Next(500, 3000)))
        Next

        Try
            Dim index As Integer = Task.WaitAny(tasks)
            Console.WriteLine("Task #{0} completed first.", tasks(index).Id)
            Console.WriteLine()
            Console.WriteLine("Status of all tasks:")
            For Each t In tasks
                Console.WriteLine("   Task #{0}: {1}", t.Id, t.Status)
            Next
        Catch e As AggregateException
            Console.WriteLine("An exception occurred.")
        End Try
    End Sub
End Module
' 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 该方法等待所有一系列任务完成。 以下示例创建 10 个任务,等待所有 10 个任务完成,然后显示其状态。

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
open System
open System.Threading
open System.Threading.Tasks

// Wait for all tasks to complete.
let tasks =
    [| for _ = 0 to 9 do
           Task.Run(fun () -> Thread.Sleep 2000) |]

try
    Task.WaitAll tasks

with :? AggregateException as ae ->
    printfn "One or more exceptions occurred: "

    for ex in ae.Flatten().InnerExceptions do
        printfn $"   {ex.Message}"

printfn "Status of completed tasks:"

for t in tasks do
    printfn $"   Task #{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
Imports System.Threading
Imports System.Threading.Tasks

Module Example6
    Public Sub Main()
        ' Wait for all tasks to complete.
        Dim tasks(9) As Task
        For i As Integer = 0 To 9
            tasks(i) = Task.Run(Sub() Thread.Sleep(2000))
        Next
        Try
            Task.WaitAll(tasks)
        Catch ae As AggregateException
            Console.WriteLine("One or more exceptions occurred: ")
            For Each ex In ae.Flatten().InnerExceptions
                Console.WriteLine("   {0}", ex.Message)
            Next
        End Try

        Console.WriteLine("Status of completed tasks:")
        For Each t In tasks
            Console.WriteLine("   Task #{0}: {1}", t.Id, t.Status)
        Next
    End Sub
End Module
' 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 个任务,其中 3 个任务正常完成,其中 3 个任务引发异常。 在其余六个任务中,有 3 个任务在开始前被取消,在执行任务时将取消 3 个任务。 异常在 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
open System
open System.Threading
open System.Threading.Tasks

// Create a cancellation token and cancel it.
let source1 = new CancellationTokenSource()
let token1 = source1.Token
source1.Cancel()
// Create a cancellation token for later cancellation.
let source2 = new CancellationTokenSource()
let token2 = source2.Token

// Create a series of tasks that will complete, be cancelled,
// timeout, or throw an exception.
let tasks =
    [| for i in 0..11 do
           match i % 4 with
           // Task should run to completion.
           | 0 -> Task.Run(fun () -> Thread.Sleep 2000)
           // Task should be set to canceled state.
           | 1 -> Task.Run(fun () -> Thread.Sleep 2000, token1)
           // Task should throw an exception.
           | 2 -> Task.Run(fun () -> NotSupportedException())
           // Task should examine cancellation token.
           | _ ->
               Task.Run(fun () ->
                   Thread.Sleep 2000

                   if token2.IsCancellationRequested then
                       token2.ThrowIfCancellationRequested()

                   Thread.Sleep 500, token2) |]


Thread.Sleep 250
source2.Cancel()

try
    Task.WaitAll tasks

with :? AggregateException as ae ->
    printfn "One or more exceptions occurred:"

    for ex in ae.InnerExceptions do
        printfn $"   {ex.GetType().Name}: {ex.Message}"

printfn "\nStatus of tasks:"

for t in tasks do
    printfn $"   Task #{t.Id}: {t.Status}"

    if isNull t.Exception |> not then
        for ex in t.Exception.InnerExceptions do
            printfn $"      {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
Imports System.Threading
Imports System.Threading.Tasks

Module Example7
    Public Sub Main()
        ' Create a cancellation token and cancel it.
        Dim source1 As New CancellationTokenSource()
        Dim token1 As CancellationToken = source1.Token
        source1.Cancel()
        ' Create a cancellation token for later cancellation.
        Dim source2 As New CancellationTokenSource()
        Dim token2 As CancellationToken = source2.Token

        ' Create a series of tasks that will complete, be cancelled, 
        ' timeout, or throw an exception.
        Dim tasks(11) As Task
        For i As Integer = 0 To 11
            Select Case i Mod 4
             ' Task should run to completion.
                Case 0
                    tasks(i) = Task.Run(Sub() Thread.Sleep(2000))
             ' Task should be set to canceled state.
                Case 1
                    tasks(i) = Task.Run(Sub() Thread.Sleep(2000), token1)
                Case 2
                    ' Task should throw an exception.
                    tasks(i) = Task.Run(Sub()
                                            Throw New NotSupportedException()
                                        End Sub)
                Case 3
                    ' Task should examine cancellation token.
                    tasks(i) = Task.Run(Sub()
                                            Thread.Sleep(2000)
                                            If token2.IsCancellationRequested Then
                                                token2.ThrowIfCancellationRequested()
                                            End If
                                            Thread.Sleep(500)
                                        End Sub, token2)
            End Select
        Next
        Thread.Sleep(250)
        source2.Cancel()

        Try
            Task.WaitAll(tasks)
        Catch ae As AggregateException
            Console.WriteLine("One or more exceptions occurred:")
            For Each ex In ae.InnerExceptions
                Console.WriteLine("   {0}: {1}", ex.GetType().Name, ex.Message)
            Next
        End Try
        Console.WriteLine()

        Console.WriteLine("Status of tasks:")
        For Each t In tasks
            Console.WriteLine("   Task #{0}: {1}", t.Id, t.Status)
            If t.Exception IsNot Nothing Then
                For Each ex In t.Exception.InnerExceptions
                    Console.WriteLine("      {0}: {1}", ex.GetType().Name,
                                 ex.Message)
                Next
            End If
        Next
    End Sub
End Module
' 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, CancellationToken, TaskCreationOptions)

使用指定的操作和创建选项初始化一个新 Task 项。

Task(Action, CancellationToken)

Task使用指定的操作和 CancellationToken.

Task(Action, TaskCreationOptions)

使用指定的操作和创建选项初始化一个新 Task 项。

Task(Action)

使用指定的操作初始化新 Task 项。

Task(Action<Object>, Object, CancellationToken, TaskCreationOptions)

使用指定的操作、状态和选项初始化一个新 Task 项。

Task(Action<Object>, Object, CancellationToken)

Task使用指定的操作、状态和 CancellationToken.

Task(Action<Object>, Object, TaskCreationOptions)

使用指定的操作、状态和选项初始化一个新 Task 项。

Task(Action<Object>, Object)

使用指定的操作和状态初始化新 Task 项。

属性

名称 说明
AsyncState

获取创建时 Task 提供的状态对象,如果未提供状态对象,则为 null。

CompletedTask

获取已成功完成的任务。

CreationOptions

TaskCreationOptions获取用于创建此任务。

CurrentId

返回当前正在执行的 TaskID。

Exception

AggregateException获取导致Task过早结束的原因。 Task如果成功完成或尚未引发任何异常,则返回null

Factory

提供对工厂方法的访问,用于创建和配置 TaskTask<TResult> 实例。

Id

获取此 Task 实例的 ID。

IsCanceled

获取此 Task 实例是否已完成执行,因为已取消。

IsCompleted

获取一个值,该值指示任务是否已完成。

IsCompletedSuccessfully

获取任务是否运行到完成。

IsFaulted

获取是否 Task 由于未经处理的异常而完成。

Status

TaskStatus获取此任务。

方法

名称 说明
ConfigureAwait(Boolean)

配置用于等待此 Task情况的 awaiter。

ConfigureAwait(ConfigureAwaitOptions)

配置用于等待此 Task情况的 awaiter。

ContinueWith(Action<Task,Object>, Object, CancellationToken, TaskContinuationOptions, TaskScheduler)

创建一个延续,该延续接收调用方提供的状态信息和取消令牌,并在目标 Task 完成时执行。 延续基于一组指定的条件执行,并使用指定的计划程序。

ContinueWith(Action<Task,Object>, Object, CancellationToken)

创建一个延续,该延续接收调用方提供的状态信息和取消令牌,并在目标 Task 完成时异步执行。

ContinueWith(Action<Task,Object>, Object, TaskContinuationOptions)

创建一个延续,该延续接收调用方提供的状态信息并在目标 Task 完成时执行。 延续基于一组指定的条件执行。

ContinueWith(Action<Task,Object>, Object, TaskScheduler)

创建一个延续,该延续接收调用方提供的状态信息并在目标 Task 完成时异步执行。 延续使用指定的计划程序。

ContinueWith(Action<Task,Object>, Object)

创建一个延续,该延续接收调用方提供的状态信息并在目标 Task 完成时执行。

ContinueWith(Action<Task>, CancellationToken, TaskContinuationOptions, TaskScheduler)

创建一个延续,该延续在目标任务根据指定的 TaskContinuationOptions任务竞争时执行。 延续接收取消令牌并使用指定的计划程序。

ContinueWith(Action<Task>, CancellationToken)

创建一个延续,该延续接收取消令牌并在目标 Task 完成时异步执行。

ContinueWith(Action<Task>, TaskContinuationOptions)

创建一个延续,该延续在目标任务根据指定的 TaskContinuationOptions任务完成时执行。

ContinueWith(Action<Task>, TaskScheduler)

创建在目标 Task 完成时异步执行的延续。 延续使用指定的计划程序。

ContinueWith(Action<Task>)

创建在目标 Task 完成时异步执行的延续。

ContinueWith<TResult>(Func<Task,Object,TResult>, Object, CancellationToken, TaskContinuationOptions, TaskScheduler)

在目标 Task 完成并返回值时,创建基于指定任务延续选项执行的延续。 延续接收调用方提供的状态信息和取消令牌,并使用指定的计划程序。

ContinueWith<TResult>(Func<Task,Object,TResult>, Object, CancellationToken)

创建在目标 Task 完成并返回值时异步执行的延续。 延续接收调用方提供的状态信息和取消令牌。

ContinueWith<TResult>(Func<Task,Object,TResult>, Object, TaskContinuationOptions)

创建一个延续,该延续在目标 Task 完成时基于指定的任务延续选项执行。 延续接收调用方提供的状态信息。

ContinueWith<TResult>(Func<Task,Object,TResult>, Object, TaskScheduler)

创建在目标 Task 完成时异步执行的延续。 延续接收调用方提供的状态信息,并使用指定的计划程序。

ContinueWith<TResult>(Func<Task,Object,TResult>, Object)

创建一个延续,该延续接收调用方提供的状态信息,并在目标 Task 完成并返回值时异步执行。

ContinueWith<TResult>(Func<Task,TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler)

创建一个根据指定的延续选项执行的延续,并返回一个值。 延续通过取消令牌并使用指定的计划程序。

ContinueWith<TResult>(Func<Task,TResult>, CancellationToken)

创建在目标 Task 完成并返回值时异步执行的延续。 延续接收取消标记。

ContinueWith<TResult>(Func<Task,TResult>, TaskContinuationOptions)

创建一个根据指定的延续选项执行的延续,并返回一个值。

ContinueWith<TResult>(Func<Task,TResult>, TaskScheduler)

创建在目标 Task 完成并返回值时异步执行的延续。 延续使用指定的计划程序。

ContinueWith<TResult>(Func<Task,TResult>)

创建在目标 Task<TResult> 完成并返回值时异步执行的延续。

Delay(Int32, CancellationToken)

创建在指定毫秒数后完成的可取消任务。

Delay(Int32)

创建在指定毫秒数后完成的任务。

Delay(TimeSpan, CancellationToken)

创建在指定时间间隔后完成的可取消任务。

Delay(TimeSpan, TimeProvider, CancellationToken)

创建在指定时间间隔后完成的可取消任务。

Delay(TimeSpan, TimeProvider)

创建在指定时间间隔后完成的任务。

Delay(TimeSpan)

创建在指定时间间隔后完成的任务。

Dispose()

释放类的 Task 当前实例使用的所有资源。

Dispose(Boolean)

Task释放其所有非托管资源。

Equals(Object)

确定指定的对象是否等于当前对象。

(继承自 Object)
FromCanceled(CancellationToken)

使用指定的取消令牌创建由于取消而完成的一个 Task

FromCanceled<TResult>(CancellationToken)

使用指定的取消令牌创建由于取消而完成的一个 Task<TResult>

FromException(Exception)

创建一个 Task 已完成且具有指定异常的异常。

FromException<TResult>(Exception)

创建一个 Task<TResult> 已完成且具有指定异常的异常。

FromResult<TResult>(TResult)

创建使用指定结果成功完成的一个 Task<TResult>

GetAwaiter()

获取用于等待此 Task项的等待程序。

GetHashCode()

用作默认哈希函数。

(继承自 Object)
GetType()

获取当前实例的 Type

(继承自 Object)
MemberwiseClone()

创建当前 Object的浅表副本。

(继承自 Object)
Run(Action, CancellationToken)

将指定的工作排入队列,以在线程池上运行,并返回表示 Task 该工作的对象。 取消令牌允许取消工作(如果尚未启动)。

Run(Action)

将指定的工作排入队列,以在线程池上运行,并返回表示 Task 该工作的对象。

Run(Func<Task>, CancellationToken)

对在线程池上运行的指定工作进行排队,并为返回的任务 function返回代理。 取消令牌允许取消工作(如果尚未启动)。

Run(Func<Task>)

对在线程池上运行的指定工作进行排队,并为返回的任务 function返回代理。

Run<TResult>(Func<Task<TResult>>, CancellationToken)

对在线程池上运行的指定工作进行排队,并为返回者Task(TResult)返回的function代理。

Run<TResult>(Func<Task<TResult>>)

对在线程池上运行的指定工作进行排队,并为返回者Task(TResult)返回的function代理。 取消令牌允许取消工作(如果尚未启动)。

Run<TResult>(Func<TResult>, CancellationToken)

将指定的工作排入队列,以在线程池上运行,并返回表示 Task(TResult) 该工作的对象。

Run<TResult>(Func<TResult>)

将指定的工作排入队列,以在线程池上运行,并返回表示 Task<TResult> 该工作的对象。 取消令牌允许取消工作(如果尚未启动)。

RunSynchronously()

Task 当前 TaskScheduler节点上同步运行 。

RunSynchronously(TaskScheduler)

Task 提供的服务器上 TaskScheduler 同步运行。

Start()

Task启动 ,计划执行到当前TaskScheduler

Start(TaskScheduler)

Task启动 ,计划将其执行到指定的 TaskScheduler

ToString()

返回一个表示当前对象的字符串。

(继承自 Object)
Wait()

等待 Task 完成执行。

Wait(CancellationToken)

等待 Task 完成执行。 如果在任务完成之前取消取消了取消令牌,则等待将终止。

Wait(Int32, CancellationToken)

等待 Task 完成执行。 如果在任务完成之前取消超时间隔或取消令牌,则等待将终止。

Wait(Int32)

等待 Task 指定的毫秒数内完成执行。

Wait(TimeSpan, CancellationToken)

等待 Task 完成执行。

Wait(TimeSpan)

Task等待指定时间间隔内完成执行。

WaitAll(IEnumerable<Task>, CancellationToken)

等待所有提供 Task 的对象完成执行,除非取消等待。

WaitAll(ReadOnlySpan<Task>)

等待所有提供 Task 的对象完成执行。

WaitAll(Task[], CancellationToken)

等待所有提供 Task 的对象完成执行,除非取消等待。

WaitAll(Task[], Int32, CancellationToken)

等待所有提供 Task 的对象在指定的毫秒内完成执行,或直到取消等待为止。

WaitAll(Task[], Int32)

等待提供 Task 的所有对象在指定的毫秒数内完成执行。

WaitAll(Task[], TimeSpan)

等待提供的所有可 Task 取消对象在指定的时间间隔内完成执行。

WaitAll(Task[])

等待所有提供 Task 的对象完成执行。

WaitAny(Task[], CancellationToken)

等待提供 Task 的任何对象完成执行,除非取消等待。

WaitAny(Task[], Int32, CancellationToken)

等待提供 Task 的任何对象在指定的毫秒内完成执行,或直到取消令牌取消为止。

WaitAny(Task[], Int32)

等待提供 Task 的任何对象在指定的毫秒数内完成执行。

WaitAny(Task[], TimeSpan)

等待提供 Task 的任何对象在指定的时间间隔内完成执行。

WaitAny(Task[])

等待提供 Task 的任何对象完成执行。

WaitAsync(CancellationToken)

获取一个 Task 将在此操作 Task 完成或指定 CancellationToken 取消请求时完成的。

WaitAsync(TimeSpan, CancellationToken)

获取一个 Task 将在此操作 Task 完成、指定的超时过期或指定 CancellationToken 取消请求时完成的。

WaitAsync(TimeSpan, TimeProvider, CancellationToken)

获取一个 Task 将在此操作 Task 完成、指定的超时过期或指定 CancellationToken 取消请求时完成的。

WaitAsync(TimeSpan, TimeProvider)

获取一个 Task 将在此操作 Task 完成或指定超时过期时完成的。

WaitAsync(TimeSpan)

获取一个 Task 将在此操作 Task 完成或指定超时过期时完成的。

WhenAll(IEnumerable<Task>)

创建一个任务,该任务将在可枚举集合中的所有 Task 对象完成时完成。

WhenAll(ReadOnlySpan<Task>)

创建一个任务,该任务将在所有提供的任务完成时完成。

WhenAll(Task[])

创建一个任务,该任务将在数组中的所有 Task 对象完成时完成。

WhenAll<TResult>(IEnumerable<Task<TResult>>)

创建一个任务,该任务将在可枚举集合中的所有 Task<TResult> 对象完成时完成。

WhenAll<TResult>(ReadOnlySpan<Task<TResult>>)

创建一个任务,该任务将在所有提供的任务完成时完成。

WhenAll<TResult>(Task<TResult>[])

创建一个任务,该任务将在数组中的所有 Task<TResult> 对象完成时完成。

WhenAny(IEnumerable<Task>)

创建一个任务,该任务将在任何提供的任务完成时完成。

WhenAny(ReadOnlySpan<Task>)

创建一个任务,该任务将在任何提供的任务完成时完成。

WhenAny(Task, Task)

创建一个任务,该任务将在提供的任一任务完成时完成。

WhenAny(Task[])

创建一个任务,该任务将在任何提供的任务完成时完成。

WhenAny<TResult>(IEnumerable<Task<TResult>>)

创建一个任务,该任务将在任何提供的任务完成时完成。

WhenAny<TResult>(ReadOnlySpan<Task<TResult>>)

创建一个任务,该任务将在任何提供的任务完成时完成。

WhenAny<TResult>(Task<TResult>, Task<TResult>)

创建一个任务,该任务将在提供的任一任务完成时完成。

WhenAny<TResult>(Task<TResult>[])

创建一个任务,该任务将在任何提供的任务完成时完成。

WhenEach(IEnumerable<Task>)

创建一个 IAsyncEnumerable<T> 将在这些任务完成时生成提供的任务。

WhenEach(ReadOnlySpan<Task>)

创建一个 IAsyncEnumerable<T> 将在这些任务完成时生成提供的任务。

WhenEach(Task[])

创建一个 IAsyncEnumerable<T> 将在这些任务完成时生成提供的任务。

WhenEach<TResult>(IEnumerable<Task<TResult>>)

创建一个 IAsyncEnumerable<T> 将在这些任务完成时生成提供的任务。

WhenEach<TResult>(ReadOnlySpan<Task<TResult>>)

创建一个 IAsyncEnumerable<T> 将在这些任务完成时生成提供的任务。

WhenEach<TResult>(Task<TResult>[])

创建一个 IAsyncEnumerable<T> 将在这些任务完成时生成提供的任务。

Yield()

创建一个可等待的任务,该任务在等待时异步生成回当前上下文。

显式接口实现

名称 说明
IAsyncResult.AsyncWaitHandle

获取一个可用于等待任务完成的项 WaitHandle

IAsyncResult.CompletedSynchronously

获取有关操作是否同步完成的指示。

扩展方法

名称 说明
AsAsyncAction(Task)

返回表示已启动任务的 Windows 运行时异步操作。

DispatcherOperationWait(Task, TimeSpan)

等待基础 DispatcherOperation 完成的指定时间量。

DispatcherOperationWait(Task)

无限期等待基础 DispatcherOperation 完成。

IsDispatcherOperationTask(Task)

返回一个值,该值指示这 Task 是否与 a DispatcherOperation.

适用于

线程安全性

除线程外Task,所有成员Dispose()都是线程安全的,可以同时从多个线程使用。

另请参阅