Sdílet prostřednictvím


System.Threading.Tasks.Task – třída

Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.

Třída Task představuje jednu operaci, která nevrací hodnotu a která se obvykle spouští asynchronně. Task objekty jsou jednou z centrálních komponent asynchronního vzoru založeného na úlohách , které byly poprvé zavedeny v rozhraní .NET Framework 4. Vzhledem k tomu, že práce prováděná objektem Task se obvykle provádí asynchronně ve vlákně fondu vláken namísto synchronně v hlavním vlákně aplikace, můžete použít Status vlastnost, stejně IsCanceledjako , IsCompleteda IsFaulted vlastnosti, určit stav úlohy. Nejčastěji se výraz lambda používá k určení práce, kterou má úkol provést.

Pro operace, které vracejí hodnoty, použijte Task<TResult> třídu.

Vytvoření instance úlohy

Následující příklad vytvoří a spustí čtyři úlohy. Tři úkoly spouštějí Action<T> delegáta s názvem action, který přijímá argument typu Object. Čtvrtý úkol spustí výraz lambda ( Action delegát), který je definován v rámci volání metody vytvoření úlohy. Každá úloha se vytvoří instance a spustí se jiným způsobem:

  • Úloha t1 je vytvořena voláním konstruktoru třídy Task, ale je spuštěn voláním jeho Start() metody až po spuštění úkolu t2 .

  • Úloha t2 se vytvoří instance a spustí se v jednom volání metody voláním TaskFactory.StartNew(Action<Object>, Object) metody.

  • Úloha t3 se vytvoří instance a spustí se v jednom volání metody voláním Run(Action) metody.

  • Úloha t4 se provádí synchronně v hlavním vlákně voláním RunSynchronously() metody.

Vzhledem k tomu, že se úloha t4 spouští synchronně, spustí se v hlavním vlákně aplikace. Zbývající úlohy se spouští asynchronně obvykle na jednom nebo více vláknech fondu vláken.

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

Vytvoření a spuštění úlohy

Instance můžete vytvářet Task různými způsoby. Nejběžnějším přístupem je volání statické Run metody. Metoda Run poskytuje jednoduchý způsob, jak spustit úlohu pomocí výchozích hodnot a bez nutnosti dalších parametrů. Následující příklad používá metodu Run(Action) ke spuštění úlohy, která smyčky a pak zobrazí počet iterací smyčky:

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

Alternativou je statická TaskFactory.StartNew metoda. Vlastnost Task.Factory vrátí TaskFactory objekt. TaskFactory.StartNew Přetížení metody umožňují zadat parametry, které se mají předat možnostem vytvoření úlohy a plánovači úloh. Následující příklad používá metodu TaskFactory.StartNew ke spuštění úkolu. Funkčně odpovídá kódu v předchozím příkladu.

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

Podrobnější příklady najdete v tématu Asynchronní programování založené na úlohách.

Oddělení vytváření a spouštění úloh

Třída Task také poskytuje konstruktory, které inicializují úlohu, ale neplánují ji pro spuštění. Z důvodů výkonu Task.Run je upřednostňovaným mechanismem pro vytváření a plánování výpočetních úloh, TaskFactory.StartNew ale ve scénářích, kde je nutné oddělit vytváření a plánování, můžete použít konstruktory a pak metodu volat Task.Start k naplánování úlohy pro provádění později.

Počkejte na dokončení úkolu.

Vzhledem k tomu, že úlohy obvykle běží asynchronně ve vlákně fondu vláken, vlákno, které vytváří a spouští úlohu, pokračuje v provádění ihned po vytvoření instance úlohy. V některých případech, když je volající vlákno hlavním vláknem aplikace, může aplikace ukončit před zahájením provádění úlohy. V jiných případech může logika vaší aplikace vyžadovat, aby volající vlákno pokračovalo ve spouštění pouze v případě, že se dokončilo provádění jedné nebo více úloh. Spuštění volajícího vlákna a asynchronních úloh, které spustí, můžete synchronizovat voláním Wait metody, která čeká na dokončení jedné nebo více úloh.

Pokud chcete počkat na dokončení jedné úlohy, můžete volat její Task.Wait metodu. Volání Wait metody blokuje volající vlákno, dokud instance jedné třídy nedokončí provádění.

Následující příklad volá bezparametrovou Wait() metodu, která čeká bezpodmínečně, dokud se úloha dokončí. Úloha simuluje práci voláním Thread.Sleep metody do režimu spánku po dobu dvou sekund.

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

Můžete také podmíněně počkat na dokončení úkolu. Volání Wait(Int32) vlákna a Wait(TimeSpan) metody blokují, dokud úloha nedokončí nebo uplyne interval časového limitu, podle toho, co nastane dříve. Vzhledem k tomu, že následující příklad spustí úlohu, která spí po dobu dvou sekund, ale definuje hodnotu časového limitu o jednu sekundu, volající vlákno blokuje do vypršení časového limitu a před dokončením provádění úkolu.

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.

Token zrušení můžete také zadat voláním Wait(CancellationToken) a Wait(Int32, CancellationToken) metodami. Pokud je vlastnost tokenu IsCancellationRequested nebo se stanetrue, když je Wait metoda spuštěna, metoda vyvolá OperationCanceledException.true

V některých případech můžete chtít počkat na dokončení první série úkolů, ale nezajímá vás, o který úkol se jedná. Pro tento účel můžete volat jedno z přetížení Task.WaitAny metody. Následující příklad vytvoří tři úkoly, z nichž každý spí pro interval určený generátorem náhodnýchčíselch Metoda WaitAny(Task[]) čeká na dokončení první úlohy. Příklad pak zobrazí informace o stavu všech tří úkolů.

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

Můžete také počkat na dokončení všech řad úkolů voláním WaitAll metody. Následující příklad vytvoří deset úkolů, počká na dokončení všech deseti a zobrazí jejich stav.

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

Všimněte si, že když počkáte na dokončení jedné nebo více úloh, všechny výjimky vyvolané ve spuštěných úkolech se rozšíří do vlákna, které volá metodu Wait , jak ukazuje následující příklad. Spustí 12 úkolů, z nichž tři jsou obvykle dokončeny a tři z nichž vyvolá výjimku. Zbývajících šest úkolů se před zahájením zruší a během provádění se zruší tři úkoly. Výjimky jsou vyvolány ve WaitAll volání metody a jsou zpracovávány blokem/trycatch.

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

Další informace o zpracovánívýjimekch

Úkoly a kultura

Počínaje desktopovými aplikacemi, které cílí na rozhraní .NET Framework 4.6, se jazyková verze vlákna, která vytváří a vyvolává úlohu, stane součástí kontextu vlákna. To znamená, že bez ohledu na aktuální jazykovou verzi vlákna, na kterém je úloha spuštěna, aktuální jazyková verze úlohy je jazyková verze volajícího vlákna. Pro aplikace, které cílí na verze rozhraní .NET Framework před rozhraním .NET Framework 4.6, je jazyková verze úlohy jazykovou verzí vlákna, na kterém se úloha spouští. Další informace najdete v části Jazykové verze a asynchronní operace založené na úlohách v CultureInfo tématu.

Poznámka:

Aplikace pro Store se řídí prostředí Windows Runtime v nastavení a získávají výchozí jazykovou verzi.

Pro vývojáře ladicího programu

Pro vývojáře, kteří implementují vlastní ladicí programy, může být užitečné několik interních a soukromých členů úlohy (můžou se změnit z verze na verzi). Pole m_taskId slouží jako záložní úložiště vlastnosti Id , ale přístup k tomuto poli přímo z ladicího programu může být efektivnější než přístup ke stejné hodnotě prostřednictvím metody getter vlastnosti ( s_taskIdCounter čítač se používá k načtení dalšího dostupného ID pro úlohu). m_stateFlags Podobně pole ukládá informace o aktuální fázi životního cyklu úkolu, informace jsou přístupné také prostřednictvím Status vlastnosti. Pole m_action ukládá odkaz na delegáta úkolu a m_stateObject pole ukládá asynchronní stav předaný úkolu vývojářem. Nakonec pro ladicí programy, které parsují rámce zásobníku, InternalWait metoda obsluhuje potenciální značku pro případ, kdy úloha zadává operaci čekání.