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 屬性 IsCanceled以及、 IsCompletedIsFaulted 屬性來判斷工作的狀態。 最常見的是,Lambda 運算式用來指定任務要執行的內容。

針對傳回值的作業,您可以使用 類別 Task<TResult>

任務實例化

下列範例會建立並執行四個工作。 三個工作會執行一個名為 Action<T>action 委派,這個委派接受一個類型為 Object 的參數。 第四個工作會執行 Lambda 運算式(委派 Action ),該運算式會在呼叫工作建立方法時內嵌定義。 每個工作都會以不同的方式具現化並執行:

  • 工作t1是透過呼叫 Task 類別的建構函式來具現化,只有在工作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 方法,等候所有一系列的工作完成。 下列範例會建立十個工作、等候這十個工作完成,然後顯示其狀態。

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 個拋出例外。 在其餘六項工作中,有三項會在開始之前取消,而執行時會取消三個工作。 例外狀況會在 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 內的「文化和以任務為基礎的非同步作業」一節。

Note

市集應用程式會遵循 Windows 執行時間設定並取得預設文化特性。

針對調試程式開發人員

對於實作自定義除錯器的開發人員,任務的數個內部和私人成員可能很有用(這些成員可能會因版本更新而改變)。 m_taskId欄位可作為屬性的Id備份存放區,不過直接從調試程式存取此欄位可能會比透過屬性的 getter 方法存取相同的值更有效率(s_taskIdCounter計數器用來擷取工作的下一個可用標識符)。 同樣地, m_stateFlags 欄位會儲存工作目前生命週期階段的相關信息,也可以透過屬性存取 Status 資訊。 欄位 m_action 儲存指向任務代理的參考,而欄位 m_stateObject 儲存開發人員傳遞給任務的非同步狀態。 最後,對於剖析堆疊框架的偵錯工具,InternalWait 方法可能作為任務進入等待操作時的標記。

建構函式

名稱 Description
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

屬性

名稱 Description
AsyncState

取得建立時 Task 提供的狀態物件,若沒有提供則為 null。

CompletedTask

拿到一個已經成功完成的任務。

CreationOptions

TaskCreationOptions 來完成這個任務。

CurrentId

回傳目前執行中的 Task的 ID 。

Exception

這也說明 AggregateException 了導致他們 Task 提前結束的原因。 若 Task 成功完成或尚未拋出任何例外,則會返回 null

Factory

提供建立與設定 Task 的工廠方法及 Task<TResult> 實例存取。

Id

這次會拿到ID Task

IsCanceled

會判斷這個 Task 實例是否因為被取消而完成執行。

IsCompleted

取得值,這個值表示工作是否已完成。

IsCompletedSuccessfully

取得工作是否執行完成。

IsFaulted

判斷是否 Task 因未處理的例外而完成。

Status

明白 TaskStatus 這個任務。

方法

名稱 Description
ConfigureAwait(Boolean)

配置一個等待者,過去會等待這個 Task

ConfigureAwait(ConfigureAwaitOptions)

配置一個等待者,過去會等待這個 Task

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)

在提供的系統上同步運行TaskTaskScheduler

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()

創造一個可等待的任務,當等待時非同步地回歸當前上下文。

明確介面實作

名稱 Description
IAsyncResult.AsyncWaitHandle

獲得 WaitHandle 一個可以用來等待任務完成的選項。

IAsyncResult.CompletedSynchronously

取得作業是否同步完成的指示。

擴充方法

名稱 Description
AsAsyncAction(Task)

傳回代表已啟動工作的 Windows 運行時間異步動作。

DispatcherOperationWait(Task, TimeSpan)

等待標的 DispatcherOperation 資產完成指定時間。

DispatcherOperationWait(Task)

無限期等待底層 DispatcherOperation 完成。

IsDispatcherOperationTask(Task)

回傳一個值,表示此值 Task 是否與 DispatcherOperation相關聯。

適用於

執行緒安全性

除了 Task之外,所有 的Dispose()成員都是執行緒安全的,且可同時從多個執行緒使用。

另請參閱