Task 類別
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
表示非同步作業。
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物件是工作型非同步模式的其中一個中央元件,先在.NET Framework 4 中引進。 由於 物件所 Task 執行的工作通常會以非同步方式線上程集區執行緒上執行,而不是在主要應用程式執行緒上同步執行,因此您可以使用 Status 屬性 IsCanceled 以及 、 IsCompleted 和 IsFaulted 屬性來判斷工作的狀態。 最常使用 Lambda 運算式來指定工作要執行的工作。
針對傳回值的作業,您可以使用 Task<TResult> 類別。
本節內容:
工作具現化範例建立和執行工作分隔工作建立和執行等候一或多個工作完成偵錯工具開發人員的工作和文化特性
工作具現化
下列範例會建立和執行四個工作。 三個 Action<T> 工作會執行名為 action
的委派,其接受 類型的 Object 引數。 第四個工作會在呼叫工作建立方法時內嵌定義委派) 執行 Lambda 運算式 Action (。 每個工作都會以不同的方式具現化並執行:
工作
t1
是藉由呼叫 Task 類別建構函式來具現化,但只有在工作啟動之後t2
,才會呼叫其 Start() 方法來啟動。工作
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 Example
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 實例可以透過各種方式建立。 從 .NET Framework 4.5 開始,最常見的方法是呼叫靜態 Run 方法。 方法 Run 提供簡單的方法來使用預設值啟動工作,而不需要其他參數。 下列範例會 Run(Action) 使用 方法來啟動迴圈的工作,然後顯示迴圈反復專案的數目:
using System;
using System.Threading.Tasks;
public class Example
{
public static async Task Main()
{
await Task.Run( () => {
// Just loop.
int ctr = 0;
for (ctr = 0; ctr <= 1000000; ctr++)
{}
Console.WriteLine("Finished {0} loop iterations",
ctr);
} );
}
}
// The example displays the following output:
// Finished 1000001 loop iterations
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 Example
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
替代方法,以及在 .NET Framework 4 中啟動工作的最常見方法是靜態 TaskFactory.StartNew 方法。 屬性 Task.Factory 會傳 TaskFactory 回 物件。 方法的多 TaskFactory.StartNew 載可讓您指定要傳遞至工作建立選項和工作排程器的參數。 下列範例會 TaskFactory.StartNew 使用 方法來啟動工作。 它的功能相當於上一個範例中的程式碼。
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Task t = Task.Factory.StartNew( () => {
// Just loop.
int ctr = 0;
for (ctr = 0; ctr <= 1000000; ctr++)
{}
Console.WriteLine("Finished {0} loop iterations",
ctr);
} );
t.Wait();
}
}
// The example displays the following output:
// Finished 1000001 loop iterations
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 Example
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.Run 或 TaskFactory.StartNew 方法是建立和排程計算工作的慣用機制,但對於必須分隔建立和排程的案例,您可以使用建構函式,然後呼叫 Task.Start 方法來排程工作以供稍後執行。
等候一或多個工作完成
由於工作通常會以非同步方式線上程集區執行緒上執行,因此建立並啟動工作的執行緒會在工作具現化後立即繼續執行。 在某些情況下,當呼叫執行緒是主要應用程式執行緒時,應用程式可能會在工作實際開始執行之前終止。 在其他人中,您的應用程式邏輯可能需要只有在一或多個工作完成執行時,呼叫執行緒才會繼續執行。 您可以藉由呼叫 Wait
方法來等候一或多個工作完成,來同步處理呼叫執行緒的執行及其啟動的非同步工作。
若要等候單一工作完成,您可以呼叫其 Task.Wait 方法。 呼叫 方法會 Wait 封鎖呼叫執行緒,直到單一類別實例完成執行為止。
下列範例會呼叫無 Wait() 參數方法,以無條件等候直到工作完成為止。 工作會呼叫 Thread.Sleep 方法以睡眠兩秒來模擬工作。
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static Random rand = new Random();
static void Main()
{
// Wait on a single task with no timeout specified.
Task taskA = Task.Run( () => Thread.Sleep(2000));
Console.WriteLine("taskA Status: {0}", taskA.Status);
try {
taskA.Wait();
Console.WriteLine("taskA Status: {0}", taskA.Status);
}
catch (AggregateException) {
Console.WriteLine("Exception in taskA.");
}
}
}
// The example displays output like the following:
// taskA Status: WaitingToRun
// taskA Status: RanToCompletion
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 Example
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 Example
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) 方法來提供取消權杖。 如果權杖的 屬性是在 true
方法執行時 Wait 或變成 true
,則方法會擲回 OperationCanceledException 。 IsCancellationRequested
在某些情況下,您可能會想要等候一系列執行中工作的第一個完成,但不要關心它是什麼工作。 為此,您可以呼叫 方法的其中一個多載 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 Example
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 Example
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 個工作,其中三個工作正常完成,其中三個會擲回例外狀況。 在其餘六個工作中,會在開始之前取消三個工作,並在執行時取消三個工作。 例外狀況會在方法呼叫中 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 Example
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
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
計數器用來擷取工作) 的下一個可用識別碼。 同樣地, m_stateFlags
欄位也會儲存工作目前生命週期階段的相關資訊,也可以透過 Status 屬性存取訊號。 欄位 m_action
會儲存工作委派的參考,而 m_stateObject
欄位會儲存開發人員傳遞給工作的非同步狀態。 最後,對於剖析堆疊框架的偵錯工具, InternalWait
此方法會在工作進入等候作業時,提供的潛在標記。
建構函式
Task(Action) |
使用指定的動作,初始化新的 Task。 |
Task(Action, CancellationToken) |
使用指定的動作和 Task,初始化新的 CancellationToken。 |
Task(Action, CancellationToken, TaskCreationOptions) |
使用指定的動作和建立選項,初始化新的 Task。 |
Task(Action, TaskCreationOptions) |
使用指定的動作和建立選項,初始化新的 Task。 |
Task(Action<Object>, Object) |
使用指定的動作和狀態,初始化新的 Task。 |
Task(Action<Object>, Object, CancellationToken) |
使用指定的動作、狀態和選項,初始化新的 Task。 |
Task(Action<Object>, Object, CancellationToken, TaskCreationOptions) |
使用指定的動作、狀態和選項,初始化新的 Task。 |
Task(Action<Object>, Object, TaskCreationOptions) |
使用指定的動作、狀態和選項,初始化新的 Task。 |
屬性
AsyncState |
取得建立 Task 時提供的狀態物件,如果未提供則為 null。 |
CompletedTask |
取得已成功完成的工作。 |
CreationOptions |
取得用來建立這個工作的 TaskCreationOptions。 |
CurrentId |
傳回目前執行之 Task 的唯一 ID。 |
Exception |
取得導致 AggregateException 不當結束的 Task。 如果 Task 順利完成,或未擲回任何例外狀況,則這會傳回 |
Factory |
提供 Factory 方法的存取,這些 Factory 方法用於建立及設定 Task 和 Task<TResult> 執行個體。 |
Id |
取得這個 Task 執行個體的 ID。 |
IsCanceled |
取得這個 Task 執行個體是否因取消才完成執行。 |
IsCompleted |
取得值,這個值表示工作是否已經完成。 |
IsCompletedSuccessfully |
取得工作是否執行到完成。 |
IsFaulted |
取得 Task 是否因未處理的例外狀況才完成。 |
Status |
取得這個工作的 TaskStatus。 |
方法
明確介面實作
IAsyncResult.AsyncWaitHandle |
取得 WaitHandle,這個項目可用來等候工作完成。 |
IAsyncResult.CompletedSynchronously |
取得作業是否已同步完成的指示。 |
擴充方法
DispatcherOperationWait(Task) |
無限期等候基礎 DispatcherOperation 完成。 |
DispatcherOperationWait(Task, TimeSpan) |
在指定的時間長度中等候,等候基礎 DispatcherOperation 完成。 |
IsDispatcherOperationTask(Task) |
傳回值,表示這個 Task 是否與 DispatcherOperation 關聯。 |
AsAsyncAction(Task) |
傳回代表已開始的動作的 Windows 執行階段非同步動作。 |
適用於
執行緒安全性
除了 以外的 Dispose() 所有成員 Task 都是安全線程,而且可以從多個執行緒同時使用。