System.Threading.Tasks.Task 类 - .NET

System.Threading.Tasks.Task 类 - .NET

本文提供了此 API 参考文档的补充说明。

该 Task 类表示不返回值且通常以异步方式执行的单个作。

Task 对象是 .NET Framework 4 中首次引入的 基于任务的异步模式 的中心组件之一。 由于对象执行的工作通常以异步方式在线程池线程上执行,而不是在主应用程序线程上同步执行Task,因此可以使用Status属性IsCanceledIsCompleted以及IsFaulted属性来确定任务的状态。 通常,lambda 表达式用于指定任务要执行的工作。

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

任务实例化

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

任务通过调用 Task t1 类构造函数进行实例化,但仅在任务Start()启动后才调用其t2方法启动。

任务t2通过在单个方法调用中调用TaskFactory.StartNew(Action, Object)方法被实例化并启动。

任务t3通过在单个方法调用中调用Run(Action)方法被实例化并启动。

任务 t4 通过调用 RunSynchronously() 方法在主线程上同步执行。

由于任务 t4 同步执行,因此它在主应用程序线程上执行。 其余任务通常在一个或多个线程池线程上异步执行。

using System;

using System.Threading;

using System.Threading.Tasks;

class Example1

{

static void Main()

{

Action 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={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 {ctr} loop iterations");

} );

}

}

// 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 Example2

{

public static void Main()

{

Task t = Task.Factory.StartNew(() =>

{

// Just loop.

int ctr = 0;

for (ctr = 0; ctr <= 1000000; ctr++)

{ }

Console.WriteLine($"Finished {ctr} loop iterations");

});

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.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: {taskA.Status}");

try {

taskA.Wait();

Console.WriteLine($"taskA Status: {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 Example5

{

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 Example4

{

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 #{tasks[index].Id} completed first.\n");

Console.WriteLine("Status of all tasks:");

foreach (var t in tasks)

Console.WriteLine($" Task #{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

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 Example3

{

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($" {ex.Message}");

}

Console.WriteLine("Status of completed tasks:");

foreach (var t in tasks)

Console.WriteLine($" 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

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 Example6

{

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($" {ex.GetType().Name}: {ex.Message}");

}

Console.WriteLine("\nStatus of tasks:");

foreach (var t in tasks)

{

Console.WriteLine($" Task #{t.Id}: {t.Status}");

if (t.Exception != null)

{

foreach (var ex in t.Exception.InnerExceptions)

Console.WriteLine($" {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 方法可以为任务进入等待操作时提供潜在的标记。

🌟 相关推荐

23家银行最新存款利率比较:城商行利率更高,存哪家最划算?
快手号一个月涨粉1000是否正常?如何让快手粉丝量快速增长?掌握正确的涨粉方法是关键!
吃不胖也是困擾!營養無法被身體吸收,營養師教你該如何調理、健康「增胖」