System.Threading.Tasks.Task-klasse
In dit artikel vindt u aanvullende opmerkingen in de referentiedocumentatie voor deze API.
De Task klasse vertegenwoordigt één bewerking die geen waarde retourneert en die meestal asynchroon wordt uitgevoerd. Taskobjecten zijn een van de centrale onderdelen van het op taken gebaseerde asynchrone patroon dat voor het eerst is geïntroduceerd in .NET Framework 4. Omdat het werk dat door een Task object wordt uitgevoerd, doorgaans asynchroon wordt uitgevoerd op een thread van een thread van een thread met threads in plaats van synchroon op de hoofdtoepassingsthread, kunt u de Status eigenschap, evenals de IsCanceled, IsCompleteden IsFaulted eigenschappen, gebruiken om de status van een taak te bepalen. Meestal wordt een lambda-expressie gebruikt om het werk op te geven dat de taak moet uitvoeren.
Voor bewerkingen die waarden retourneren, gebruikt u de Task<TResult> klasse.
Taak instantiëring
In het volgende voorbeeld worden vier taken gemaakt en uitgevoerd. Drie taken voeren een Action<T> gemachtigde met de naam action
uit, die een argument van het type Objectaccepteert. Een vierde taak voert een lambda-expressie (een Action gemachtigde) uit die inline is gedefinieerd in de aanroep van de methode voor het maken van taken. Elke taak wordt geïnstantieerd en op een andere manier uitgevoerd:
De taak
t1
wordt geïnstantieerd door een taakklasseconstructor aan te roepen, maar wordt pas gestart door de Start() methode aan te roepen nadat de taakt2
is gestart.De taak
t2
wordt geïnstantieerd en gestart in één methode-aanroep door de methode aan te TaskFactory.StartNew(Action<Object>, Object) roepen.De taak
t3
wordt geïnstantieerd en gestart in één methode-aanroep door de methode aan te Run(Action) roepen.De taak
t4
wordt synchroon uitgevoerd op de hoofdthread door de methode aan te RunSynchronously() roepen.
Omdat de taak t4
synchroon wordt uitgevoerd, wordt deze uitgevoerd op de hoofdtoepassingsthread. De resterende taken worden asynchroon uitgevoerd op een of meer threadpoolthreads.
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={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
Een taak maken en uitvoeren
U kunt op verschillende manieren exemplaren maken Task . De meest voorkomende benadering is het aanroepen van de statische Run methode. De Run methode biedt een eenvoudige manier om een taak te starten met behulp van standaardwaarden en zonder extra parameters. In het volgende voorbeeld wordt de Run(Action) methode gebruikt om een taak te starten die wordt herhaald en vervolgens het aantal lusiteraties weer te geven:
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
Een alternatief is de statische TaskFactory.StartNew methode. De Task.Factory eigenschap retourneert een TaskFactory object. Met overbelastingen van de TaskFactory.StartNew methode kunt u parameters opgeven die moeten worden doorgegeven aan de opties voor het maken van taken en een taakplanner. In het volgende voorbeeld wordt de TaskFactory.StartNew methode gebruikt om een taak te starten. Het is functioneel gelijk aan de code in het vorige voorbeeld.
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 {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
Zie Asynchrone programmering op basis van taken voor meer volledige voorbeelden.
Afzonderlijke taak maken en uitvoeren
De Task klasse biedt ook constructors die de taak initialiseren, maar die deze niet plannen voor uitvoering. Om prestatieredenen is de Task.Run of TaskFactory.StartNew methode het voorkeursmechanisme voor het maken en plannen van rekentaken, maar voor scenario's waarbij het maken en plannen moet worden gescheiden, kunt u de constructors gebruiken en vervolgens de methode aanroepen om de Task.Start taak op een later tijdstip te plannen voor uitvoering.
Wacht totdat een taak is voltooid
Omdat taken doorgaans asynchroon worden uitgevoerd op een thread van een threadgroep, gaat de thread die de taak maakt en start, door met de uitvoering zodra de taak is geïnstantieerd. In sommige gevallen kan de app, wanneer de aanroepende thread de belangrijkste thread van de toepassing is, worden beëindigd voordat de taak daadwerkelijk begint met de uitvoering. In andere gevallen is het mogelijk dat de logica van uw toepassing vereist dat de aanroepende thread alleen wordt uitgevoerd wanneer een of meer taken de uitvoering hebben voltooid. U kunt de uitvoering van de aanroepende thread en de asynchrone taken die worden gestart synchroniseren door een Wait
methode aan te roepen om te wachten tot een of meer taken zijn voltooid.
Als u wilt wachten tot één taak is voltooid, kunt u de Task.Wait bijbehorende methode aanroepen. Een aanroep van de methode blokkeert de Wait aanroepende thread totdat de uitvoering van het exemplaar van één klasse is voltooid.
In het volgende voorbeeld wordt de methode zonder parameters Wait() aangeroepen om onvoorwaardelijke te wachten totdat een taak is voltooid. De taak simuleert werk door de Thread.Sleep methode aan te roepen om twee seconden te slapen.
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
U kunt ook voorwaardelijk wachten totdat een taak is voltooid. De Wait(Int32) en Wait(TimeSpan) methoden blokkeren de aanroepende thread totdat de taak is voltooid of een time-outinterval is verstreken, afhankelijk van wat het eerst voorkomt. Aangezien in het volgende voorbeeld een taak wordt gestart die twee seconden in slaapstand gaat, maar een time-outwaarde van één seconde definieert, blokkeert de aanroepende thread totdat de time-out verloopt en voordat de taak is uitgevoerd.
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.
U kunt ook een annuleringstoken opgeven door de Wait(CancellationToken) en Wait(Int32, CancellationToken) methoden aan te roepen. Als de eigenschap van IsCancellationRequested het token is true
of wordt true
terwijl de Wait methode wordt uitgevoerd, genereert de methode een OperationCanceledException.
In sommige gevallen wilt u misschien wachten tot de eerste van een reeks uitvoertaken is voltooid, maar het maakt niet uit welke taak het is. Hiervoor kunt u een van de overbelastingen van de Task.WaitAny methode aanroepen. In het volgende voorbeeld worden drie taken gemaakt, die elk een interval hebben dat wordt bepaald door een generator voor willekeurige getallen. De WaitAny(Task[]) methode wacht totdat de eerste taak is voltooid. In het voorbeeld wordt vervolgens informatie weergegeven over de status van alle drie de taken.
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 #{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
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
U kunt ook wachten totdat alle taken zijn voltooid door de methode aan te WaitAll roepen. In het volgende voorbeeld worden tien taken gemaakt, wordt gewacht tot alle tien zijn voltooid en wordt de status weergegeven.
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(" {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
Houd er rekening mee dat wanneer u wacht tot een of meer taken zijn voltooid, eventuele uitzonderingen in de actieve taken worden doorgegeven in de thread die de Wait
methode aanroept, zoals in het volgende voorbeeld wordt weergegeven. Er worden 12 taken gestart, waarvan drie normaal zijn voltooid en waarvan er drie een uitzondering veroorzaken. Van de resterende zes taken worden drie geannuleerd voordat ze worden gestart en drie worden geannuleerd terwijl ze worden uitgevoerd. Uitzonderingen worden gegenereerd in de WaitAll methode-aanroep en worden verwerkt door een try
/catch
blok.
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(" {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
Zie Uitzonderingsafhandeling voor meer informatie over het verwerken van uitzonderingen in asynchrone bewerkingen op basis van taken.
Taken en cultuur
Vanaf desktop-apps die zich richten op .NET Framework 4.6, wordt de cultuur van de thread die een taak maakt en aanroept, onderdeel van de context van de thread. Dit is, ongeacht de huidige cultuur van de thread waarop de taak wordt uitgevoerd, de huidige cultuur van de taak is de cultuur van de aanroepende thread. Voor apps die gericht zijn op versies van .NET Framework vóór .NET Framework 4.6, is de cultuur van de taak de cultuur van de thread waarop de taak wordt uitgevoerd. Zie de sectie 'Asynchrone bewerkingen op basis van cultuur en taken' in het CultureInfo onderwerp voor meer informatie.
Notitie
Store-apps volgen de Windows Runtime in de instelling en krijgen de standaardcultuur.
Voor ontwikkelaars van foutopsporingsprogramma's
Voor ontwikkelaars die aangepaste foutopsporingsprogramma's implementeren, kunnen verschillende interne en persoonlijke leden van de taak nuttig zijn (deze kunnen veranderen van release naar release). Het m_taskId
veld fungeert als het backing-archief voor de Id eigenschap, maar het openen van dit veld rechtstreeks vanuit een foutopsporingsprogramma kan efficiënter zijn dan het openen van dezelfde waarde via de gettermethode van de eigenschap (de s_taskIdCounter
teller wordt gebruikt om de volgende beschikbare id voor een taak op te halen). Op dezelfde manier slaat het m_stateFlags
veld informatie op over de huidige levenscyclusfase van de taak, informatie die ook toegankelijk is via de Status eigenschap. In m_action
het veld wordt een verwijzing opgeslagen naar de gemachtigde van de taak en in het m_stateObject
veld wordt de asynchrone status opgeslagen die door de ontwikkelaar aan de taak is doorgegeven. Ten slotte dient de InternalWait
methode voor foutopsporingsprogramma's die stackframes parseren, een mogelijke markering voor wanneer een taak een wachtbewerking invoert.