Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Anmärkning
Den här artikeln innehåller ytterligare kommentarer till referensdokumentationen för det här API:et.
Klassen Task representerar en enskild åtgärd som inte returnerar ett värde och som vanligtvis körs asynkront. Task objekt är en av de centrala komponenterna i det aktivitetsbaserade asynkrona mönster som först introducerades i .NET Framework 4. Eftersom det arbete som utförs av ett Task objekt vanligtvis körs asynkront på en trådpooltråd i stället för synkront på huvudprogramtråden Status , kan du använda egenskapen, liksom IsCanceledegenskaperna , IsCompletedoch IsFaulted för att fastställa tillståndet för en uppgift. Oftast används ett lambda-uttryck för att ange det arbete som uppgiften ska utföra.
För åtgärder som returnerar värden använder Task<TResult> du klassen .
Uppgiftsinstansiering
I följande exempel skapas och körs fyra uppgifter. Tre uppgifter utför en Action<T> delegat med namnet action, som accepterar ett argument av typen Object. En fjärde uppgift kör ett lambda-uttryck (en Action delegat) som definieras direkt vid anropet av metoden för att skapa uppgiften. Varje uppgift instansieras och körs på ett annat sätt:
Aktiviteten
t1instansieras genom att anropa en konstruktor för aktivitetsklass, men startas genom att anropa dess Start() metod först när aktivitetent2har startats.Aktiviteten
t2instansieras och startas i ett enda metodanrop genom att anropa TaskFactory.StartNew(Action<Object>, Object) metoden.Aktiviteten
t3instansieras och startas i ett enda metodanrop genom att anropa Run(Action) metoden.Uppgiften
t4körs synkront på huvudtråden genom att anropa RunSynchronously() metoden.
Eftersom aktiviteten t4 körs synkront körs den på huvudprogramtråden. De återstående uppgifterna körs vanligtvis asynkront på en eller flera trådar i en trådpool.
using System;
using System.Threading;
using System.Threading.Tasks;
class Example1
{
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={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
Skapa och köra en uppgift
Du kan skapa Task instanser på flera olika sätt. Den vanligaste metoden är att anropa den statiska Run metoden. Metoden Run är ett enkelt sätt att starta en uppgift med standardvärden och utan att kräva ytterligare parametrar. I följande exempel används Run(Action) metoden för att starta en aktivitet som loopar och sedan visar antalet loop-iterationer:
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
Ett alternativ är den statiska TaskFactory.StartNew metoden. Egenskapen Task.Factory returnerar ett TaskFactory objekt. Med överlagringar av TaskFactory.StartNew metoden kan du ange parametrar som ska skickas till alternativen för att skapa aktiviteter och en schemaläggare. I följande exempel används TaskFactory.StartNew metoden för att starta en uppgift. Den är funktionellt likvärdig med koden i föregående exempel.
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
Mer fullständiga exempel finns i Aktivitetsbaserad asynkron programmering.
Separat skapande och körning av uppgift
Klassen Task innehåller även konstruktorer som initierar uppgiften men som inte schemalägger den för körning. För prestandaskäl är metoderna Task.Run och TaskFactory.StartNew de bästa mekanismerna för att skapa och schemalägga beräkningsuppgifter, men för scenarier där skapande och schemaläggning måste separeras kan du använda konstruktorerna och sedan anropa metoden Task.Start för att schemalägga uppgiften för körning vid ett senare tillfälle.
Vänta tills en uppgift har slutförts
Eftersom aktiviteter vanligtvis körs asynkront på en trådpooltråd fortsätter tråden som skapar och startar uppgiften att köras så snart aktiviteten har instansierats. I vissa fall, när den anropande tråden är huvudprogramtråden, kan appen avslutas innan uppgiften faktiskt börjar köras. I andra fall kan programmets logik kräva att den anropande tråden endast fortsätter att köra när en eller flera uppgifter har slutfört körningen. Du kan synkronisera körningen av den anropande tråden och de asynkrona uppgifter som startas genom att anropa en Wait metod för att vänta tills en eller flera uppgifter har slutförts.
Om du vill vänta tills en enskild uppgift har slutförts kan du anropa dess Task.Wait metod. Ett anrop till Wait metoden blockerar den anropande tråden tills den enskilda klassinstansen har slutfört körningen.
I följande exempel anropas den parameterlösa Wait() metoden för att vänta villkorslöst tills en uppgift har slutförts. Uppgiften simulerar arbetet genom att anropa Thread.Sleep-metoden för att sova i två sekunder.
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
Du kan också villkorligt vänta tills en uppgift har slutförts. Metoderna Wait(Int32) och Wait(TimeSpan) blockerar den anropande tråden tills aktiviteten har slutförts eller ett tidsgränsintervall förflutit, beroende på vilket som kommer först. Eftersom följande exempel startar en aktivitet som ligger i viloläge i två sekunder men definierar ett timeout-värde på en sekund blockeras den anropande tråden tills tidsgränsen upphör att gälla och innan aktiviteten har slutfört körningen.
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.
Du kan också ange en annulleringstoken genom att anropa Wait(CancellationToken) metoderna och Wait(Int32, CancellationToken) . Om tokens IsCancellationRequested egenskap är true eller blir true när Wait metoden körs, genererar metoden en OperationCanceledException.
I vissa fall kanske du vill vänta tills den första i en serie av utförande uppgifter har slutförts, men det spelar ingen roll vilken uppgift det är. För det här ändamålet kan du anropa en av överlagringarna av Task.WaitAny metoden. I följande exempel skapas tre uppgifter som var och en ligger i viloläge för ett intervall som bestäms av en slumptalsgenerator. Metoden WaitAny(Task[]) väntar på att den första aktiviteten ska slutföras. Exemplet visar sedan information om status för alla tre aktiviteterna.
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
Du kan också vänta tills alla en serie uppgifter har slutförts genom att anropa WaitAll metoden. I följande exempel skapas tio uppgifter, väntar på att alla tio ska slutföras och visar sedan deras status.
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
Observera att när du väntar på att en eller flera aktiviteter ska slutföras sprids eventuella undantag som utlöses i de aktiviteter som körs i tråden som anropar Wait metoden, vilket visas i följande exempel. Den startar 12 uppgifter, varav tre slutförs normalt och tre av dem utlöser ett undantag. Av de återstående sex aktiviteterna avbryts tre innan de startas och tre avbryts medan de körs. Undantag utlöses i metodanropet WaitAll och hanteras av ett try/catch block.
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
Mer information om undantagshantering i aktivitetsbaserade asynkrona åtgärder finns i Undantagshantering.
Uppgifter och kultur
Från och med skrivbordsappar som riktar sig mot .NET Framework 4.6 blir kulturen i tråden som skapar och anropar en uppgift en del av trådens kontext. Oavsett den aktuella kulturen i den tråd som aktiviteten körs på är aktivitetens aktuella kultur kulturen i den anropande tråden. För appar som riktar in sig på versioner av .NET Framework före .NET Framework 4.6 är aktivitetens kultur kulturen i den tråd som aktiviteten körs på. Mer information finns i avsnittet "Kultur och aktivitetsbaserade asynkrona åtgärder" i ämnet CultureInfo .
Anmärkning
Store-appar följer Windows Runtime för att ställa in och hämta standardkulturen.
För felsökningsutvecklare
För utvecklare som implementerar anpassade felsökningsprogram kan flera interna och privata uppgiftsmedlemmar vara användbara (dessa kan ändras från version till version). Fältet m_taskId fungerar som lagringsplats för Id egenskapen, men det kan vara effektivare att komma åt det här fältet direkt från ett felsökningsprogram än att komma åt samma värde via egenskapens getter-metod (räknaren s_taskIdCounter används för att hämta nästa tillgängliga ID för en aktivitet).
m_stateFlags På samma sätt lagrar fältet information om aktivitetens aktuella livscykelsteg, information som också är tillgänglig via egenskapenStatus. Fältet m_action lagrar en referens till uppgiftens delegat, och fältet m_stateObject lagrar det asynkrona tillstånd som skickas till uppgiften av utvecklaren. Slutligen, för felsökningsprogram som parsar stackramar, InternalWait fungerar metoden som en potentiell markör för när en aktivitet anger en vänteåtgärd.