Asynchronní programování založené na úloháchTask-based asynchronous programming

Task Parallel Library (TPL) je založen na konceptu úlohy, která představuje asynchronní operaci.The Task Parallel Library (TPL) is based on the concept of a task, which represents an asynchronous operation. V některých způsobech se úkol podobá vláknu nebo pracovní položce ThreadPool, ale na vyšší úrovni abstrakce.In some ways, a task resembles a thread or ThreadPool work item, but at a higher level of abstraction. Pojem úkol paralelismus odkazuje na jednu nebo více nezávislých úloh, které jsou spuštěny souběžně.The term task parallelism refers to one or more independent tasks running concurrently. Úlohy poskytují dvě hlavní výhody:Tasks provide two primary benefits:

  • Větší škálovatelnost a efektivnější využívání systémových prostředků.More efficient and more scalable use of system resources.

    Na pozadí jsou úlohy zařazené do ThreadPool, což bylo vylepšené s algoritmy, které určují a upravují počet vláken, která poskytují vyrovnávání zatížení pro maximalizaci propustnosti.Behind the scenes, tasks are queued to the ThreadPool, which has been enhanced with algorithms that determine and adjust to the number of threads and that provide load balancing to maximize throughput. Díky tomu jsou úlohy relativně lehké a lze jich vytvořit mnoho, takže lze dosáhnout jemně odstupňovaného paralelismu.This makes tasks relatively lightweight, and you can create many of them to enable fine-grained parallelism.

  • Více programového ovládání než je k dispozici s vláknem nebo pracovní položkou.More programmatic control than is possible with a thread or work item.

    Úlohy a architektura kolem nich vytvořená poskytují bohatou sadu rozhraní (API), která podporují čekání, zrušení, pokračování, robustní zpracování výjimek, podrobný stav, vlastní plánování a další.Tasks and the framework built around them provide a rich set of APIs that support waiting, cancellation, continuations, robust exception handling, detailed status, custom scheduling, and more.

Pro oba z těchto důvodů je v rozhraní .NET Framework TPL upřednostňovaným rozhraním API pro psaní vícevláknového, asynchronního a paralelního kódu.For both of these reasons, in the .NET Framework, TPL is the preferred API for writing multi-threaded, asynchronous, and parallel code.

Implicitní vytváření a spouštění úlohCreating and running tasks implicitly

Metoda Parallel.Invoke poskytuje pohodlný způsob, jak souběžně spustit libovolný počet libovolných příkazů.The Parallel.Invoke method provides a convenient way to run any number of arbitrary statements concurrently. Stačí předat delegáta Action pro každou položku práce.Just pass in an Action delegate for each item of work. Nejsnadnější způsob, jak vytvořit tyto delegáty, je použití lambda výrazů.The easiest way to create these delegates is to use lambda expressions. Lambda výraz může buďto volat pojmenovanou metodu, nebo poskytnout vložený kód.The lambda expression can either call a named method or provide the code inline. Následující příklad ukazuje základní volání Invoke, které vytvoří a spustí dvě úlohy, které běží souběžně.The following example shows a basic Invoke call that creates and starts two tasks that run concurrently. První úloha je reprezentována výrazem lambda, který volá metodu s názvem DoSomeWorka druhá úloha je reprezentována výrazem lambda, který volá metodu s názvem DoSomeOtherWork.The first task is represented by a lambda expression that calls a method named DoSomeWork, and the second task is represented by a lambda expression that calls a method named DoSomeOtherWork.

Poznámka

Tato dokumentace používá k definování delegátů v TPL lambda výrazy.This documentation uses lambda expressions to define delegates in TPL. Pokud nejste obeznámeni s lambda výrazy v C# nebo Visual Basic, přečtěte si téma lambda výrazy v PLINQ a TPL.If you are not familiar with lambda expressions in C# or Visual Basic, see Lambda Expressions in PLINQ and TPL.

Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());
Parallel.Invoke(Sub() DoSomeWork(), Sub() DoSomeOtherWork())

Poznámka

Počet instancí Task, které jsou vytvořeny na pozadí pomocí Invoke, nemusí být nutně roven počtu poskytnutých delegátů.The number of Task instances that are created behind the scenes by Invoke is not necessarily equal to the number of delegates that are provided. Knihovna TPL může využít různé optimalizace, zejména s velkým počtem delegátů.The TPL may employ various optimizations, especially with large numbers of delegates.

Další informace naleznete v tématu How to: use Parallel. Invoke pro provádění paralelních operací.For more information, see How to: Use Parallel.Invoke to Execute Parallel Operations.

Chcete-li získat větší kontrolu nad prováděním úloh nebo vrátit hodnotu z úkolu, je nutné pracovat s objekty Task více explicitně.For greater control over task execution or to return a value from the task, you have to work with Task objects more explicitly.

Explicitní vytváření a spouštění úlohCreating and running tasks explicitly

Úloha, která nevrací hodnotu, je reprezentována třídou System.Threading.Tasks.Task.A task that does not return a value is represented by the System.Threading.Tasks.Task class. Úloha, která vrací hodnotu, je reprezentována třídou System.Threading.Tasks.Task<TResult>, která dědí z Task.A task that returns a value is represented by the System.Threading.Tasks.Task<TResult> class, which inherits from Task. Objekt úlohy zpracovává podrobnosti infrastruktury a poskytuje metody a vlastnosti, které jsou přístupné z volajícího vlákna po celou dobu trvání úlohy.The task object handles the infrastructure details and provides methods and properties that are accessible from the calling thread throughout the lifetime of the task. Můžete například kdykoli přistupovat k vlastnosti Status úlohy a zjistit, zda byla spuštěna, dokončena, zrušena, nebo byla vyvolána výjimka.For example, you can access the Status property of a task at any time to determine whether it has started running, ran to completion, was canceled, or has thrown an exception. Stav je reprezentován výčtem TaskStatus.The status is represented by a TaskStatus enumeration.

Když je vytvořena úloha, je jí zadán uživatelský delegát, jenž provádí zapouzdření kódu, který úloha provede.When you create a task, you give it a user delegate that encapsulates the code that the task will execute. Tento delegát může být vyjádřen jako pojmenovaný delegát, anonymní metoda nebo lambda výraz.The delegate can be expressed as a named delegate, an anonymous method, or a lambda expression. Lambda výrazy mohou obsahovat volání pojmenované metody, jak ukazuje následující příklad.Lambda expressions can contain a call to a named method, as shown in the following example. Všimněte si, že příklad obsahuje volání metody Task.Wait, aby bylo zajištěno, že úloha dokončí provádění před ukončením aplikace v režimu konzoly.Note that the example includes a call to the Task.Wait method to ensure that the task completes execution before the console mode application ends.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      Thread.CurrentThread.Name = "Main";

      // Create a task and supply a user delegate by using a lambda expression. 
      Task taskA = new Task( () => Console.WriteLine("Hello from taskA."));
      // Start the task.
      taskA.Start();

      // Output a message from the calling thread.
      Console.WriteLine("Hello from thread '{0}'.", 
                        Thread.CurrentThread.Name);
      taskA.Wait();
   }
}
// The example displays output like the following:
//       Hello from thread 'Main'.
//       Hello from taskA.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
        Thread.CurrentThread.Name = "Main"
        
        ' Create a task and supply a user delegate by using a lambda expression. 
        Dim taskA = New Task(Sub() Console.WriteLine("Hello from taskA."))
        ' Start the task.
        taskA.Start()

        ' Output a message from the calling thread.
        Console.WriteLine("Hello from thread '{0}'.", 
                          Thread.CurrentThread.Name)
        taskA.Wait()
   End Sub
End Module
' The example displays output like the following:
'    Hello from thread 'Main'.
'    Hello from taskA.

Můžete také použít metody Task.Run k vytvoření a spuštění úlohy v jedné operaci.You can also use the Task.Run methods to create and start a task in one operation. Chcete-li spravovat úlohu, metody Run používají výchozí Plánovač úloh bez ohledu na to, který Plánovač úloh je přidružen k aktuálnímu vláknu.To manage the task, the Run methods use the default task scheduler, regardless of which task scheduler is associated with the current thread. Metody Run jsou preferovaným způsobem, jak vytvářet a spouštět úlohy, když není potřeba větší kontrola nad vytvořením a plánováním úkolu.The Run methods are the preferred way to create and start tasks when more control over the creation and scheduling of the task is not needed.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      Thread.CurrentThread.Name = "Main";

      // Define and run the task.
      Task taskA = Task.Run( () => Console.WriteLine("Hello from taskA."));

      // Output a message from the calling thread.
      Console.WriteLine("Hello from thread '{0}'.", 
                          Thread.CurrentThread.Name);
      taskA.Wait();
   }
}
// The example displays output like the following:
//       Hello from thread 'Main'.
//       Hello from taskA.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
        Thread.CurrentThread.Name = "Main"
        
        Dim taskA As Task = Task.Run(Sub() Console.WriteLine("Hello from taskA."))

        ' Output a message from the calling thread.
        Console.WriteLine("Hello from thread '{0}'.", 
                          Thread.CurrentThread.Name)
        taskA.Wait()
   End Sub
End Module
' The example displays output like the following:
'    Hello from thread 'Main'.
'    Hello from taskA.

Můžete také použít metodu TaskFactory.StartNew k vytvoření a spuštění úlohy v jedné operaci.You can also use the TaskFactory.StartNew method to create and start a task in one operation. Tuto metodu použijte, když vytváření a plánování nemusí být odděleno a vyžadujete další možnosti vytvoření úlohy nebo použití konkrétního plánovače nebo pokud potřebujete předat další stav do úlohy, kterou můžete načíst prostřednictvím jeho Task.AsyncState vlastností, jak je znázorněno v následujícím příkladu.Use this method when creation and scheduling do not have to be separated and you require additional task creation options or the use of a specific scheduler, or when you need to pass additional state into the task that you can retrieve through its Task.AsyncState property, as shown in the following example.

using System;
using System.Threading;
using System.Threading.Tasks;

class CustomData
{
   public long CreationTime;
   public int Name; 
   public int ThreadNum;
}

public class Example
{
   public static void Main()
   {
      Task[] taskArray = new Task[10];
      for (int i = 0; i < taskArray.Length; i++) {
         taskArray[i] = Task.Factory.StartNew( (Object obj ) => {
                                                  CustomData data = obj as CustomData;
                                                  if (data == null) 
                                                     return;
                                     
                                                  data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
                                               },
                                               new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks} );
      }
      Task.WaitAll(taskArray);     
      foreach (var task in taskArray) {
         var data = task.AsyncState as CustomData;
         if (data != null)
            Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
                              data.Name, data.CreationTime, data.ThreadNum);
      }                     
   }
}
// The example displays output like the following:
//       Task #0 created at 635116412924597583 on thread #3.
//       Task #1 created at 635116412924607584 on thread #4.
//       Task #3 created at 635116412924607584 on thread #4.
//       Task #4 created at 635116412924607584 on thread #4.
//       Task #2 created at 635116412924607584 on thread #3.
//       Task #6 created at 635116412924607584 on thread #3.
//       Task #5 created at 635116412924607584 on thread #4.
//       Task #8 created at 635116412924607584 on thread #4.
//       Task #7 created at 635116412924607584 on thread #3.
//       Task #9 created at 635116412924607584 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks

Class CustomData
   Public CreationTime As Long
   Public Name As Integer
   Public ThreadNum As Integer
End Class

Module Example
   Public Sub Main()
      Dim taskArray(9) As Task
      For i As Integer = 0 To taskArray.Length - 1
         taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
                                                 Dim data As CustomData = TryCast(obj, CustomData)
                                                 If data Is Nothing Then Return
                                     
                                                 data.ThreadNum = Thread.CurrentThread.ManagedThreadId
                                              End Sub,
                                              New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks} )
      Next
      Task.WaitAll(taskArray)     

      For Each task In taskArray
         Dim data = TryCast(task.AsyncState, CustomData)
         If data IsNot Nothing Then
            Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
                              data.Name, data.CreationTime, data.ThreadNum)
         End If
      Next
   End Sub
End Module
' The example displays output like the following:
'    Task #0 created at 635116451245250515, ran on thread #3, RanToCompletion
'    Task #1 created at 635116451245270515, ran on thread #4, RanToCompletion
'    Task #2 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #3 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #4 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #5 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #6 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #7 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #8 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #9 created at 635116451245270515, ran on thread #3, RanToCompletion

Task a Task<TResult> každé vystavení vlastnosti statického Factory, která vrací výchozí instanci TaskFactory, takže můžete volat metodu jako Task.Factory.StartNew().Task and Task<TResult> each expose a static Factory property that returns a default instance of TaskFactory, so that you can call the method as Task.Factory.StartNew(). Také v následujícím příkladu, protože jsou úkoly typu System.Threading.Tasks.Task<TResult>, mají každý z nich vlastnost Public Task<TResult>.Result, která obsahuje výsledek výpočtu.Also, in the following example, because the tasks are of type System.Threading.Tasks.Task<TResult>, they each have a public Task<TResult>.Result property that contains the result of the computation. Úlohy běží asynchronně a mohou být dokončeny v libovolném pořadí.The tasks run asynchronously and may complete in any order. Je-li vlastnost Result k dispozici před dokončením výpočtu, vlastnost blokuje volající vlákno, dokud nebude hodnota k dispozici.If the Result property is accessed before the computation finishes, the property blocks the calling thread until the value is available.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
        Task<Double>[] taskArray = { Task<Double>.Factory.StartNew(() => DoComputation(1.0)),
                                     Task<Double>.Factory.StartNew(() => DoComputation(100.0)), 
                                     Task<Double>.Factory.StartNew(() => DoComputation(1000.0)) };

        var results = new Double[taskArray.Length];
        Double sum = 0;
        
        for (int i = 0; i < taskArray.Length; i++) {
            results[i] = taskArray[i].Result;
            Console.Write("{0:N1} {1}", results[i], 
                              i == taskArray.Length - 1 ? "= " : "+ ");
            sum += results[i];
        }
        Console.WriteLine("{0:N1}", sum);
   }

   private static Double DoComputation(Double start)
   {
      Double sum = 0;
      for (var value = start; value <= start + 10; value += .1)
         sum += value;

      return sum; 
   }
}
// The example displays the following output:
//        606.0 + 10,605.0 + 100,495.0 = 111,706.0
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
        Dim taskArray() = { Task(Of Double).Factory.StartNew(Function() DoComputation(1.0)),
                            Task(Of Double).Factory.StartNew(Function() DoComputation(100.0)), 
                            Task(Of Double).Factory.StartNew(Function() DoComputation(1000.0)) }

        Dim results(taskArray.Length - 1) As Double
        Dim sum As Double
        
        For i As Integer = 0 To taskArray.Length - 1
            results(i) = taskArray(i).Result
            Console.Write("{0:N1} {1}", results(i), 
                              If(i = taskArray.Length - 1, "= ", "+ "))
            sum += results(i)
        Next
        Console.WriteLine("{0:N1}", sum)
   End Sub
   
   Private Function DoComputation(start As Double) As Double
      Dim sum As Double
      For value As Double = start To start + 10 Step .1
         sum += value
      Next
      Return sum 
   End Function
End Module
' The example displays the following output:
'       606.0 + 10,605.0 + 100,495.0 = 111,706.0

Další informace najdete v tématu Postupy: vrácení hodnoty z úkolu.For more information, see How to: Return a Value from a Task.

Při použití lambda výrazu k vytvoření delegáta máte přístup ke všem proměnným, které jsou v daném okamžiku viditelné ve zdrojovém kódu.When you use a lambda expression to create a delegate, you have access to all the variables that are visible at that point in your source code. V některých případech, zejména v rámci smyčky, však lambda nezachytí proměnnou podle očekávání.However, in some cases, most notably within loops, a lambda doesn't capture the variable as expected. Pouze zachycuje konečnou hodnotu, nikoli mutaci hodnoty po každé iteraci.It only captures the final value, not the value as it mutates after each iteration. Následující příklad ukazuje tento problém.The following example illustrates the problem. Předá do výrazu lambda výraz, který vytvoří instanci objektu CustomData a použije počítadlo smyčky jako identifikátoru objektu.It passes a loop counter to a lambda expression that instantiates a CustomData object and uses the loop counter as the object's identifier. Jak výstup z příkladu ukazuje, každý objekt CustomData má stejný identifikátor.As the output from the example shows, each CustomData object has an identical identifier.

using System;
using System.Threading;
using System.Threading.Tasks;

class CustomData
{
   public long CreationTime;
   public int Name; 
   public int ThreadNum;
}

public class Example
{
   public static void Main()
   {
      // Create the task object by using an Action(Of Object) to pass in the loop
      // counter. This produces an unexpected result.
      Task[] taskArray = new Task[10];
      for (int i = 0; i < taskArray.Length; i++) {
         taskArray[i] = Task.Factory.StartNew( (Object obj) => {
                                                 var data = new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks}; 
                                                 data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
                                                 Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
                                                                   data.Name, data.CreationTime, data.ThreadNum);
                                               },
                                              i );
      }
      Task.WaitAll(taskArray);     
   }
}
// The example displays output like the following:
//       Task #10 created at 635116418427727841 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427727841 on thread #3.
//       Task #10 created at 635116418427747843 on thread #3.
//       Task #10 created at 635116418427747843 on thread #3.
//       Task #10 created at 635116418427737842 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks

Class CustomData
   Public CreationTime As Long
   Public Name As Integer
   Public ThreadNum As Integer
End Class

Module Example
   Public Sub Main()
      ' Create the task object by using an Action(Of Object) to pass in the loop
      ' counter. This produces an unexpected result.
      Dim taskArray(9) As Task
      For i As Integer = 0 To taskArray.Length - 1
         taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
                                                 Dim data As New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks} 
                                                 data.ThreadNum = Thread.CurrentThread.ManagedThreadId
                                                 Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
                                                                   data.Name, data.CreationTime, data.ThreadNum)
                                              End Sub,
                                              i )
      Next
      Task.WaitAll(taskArray)     
   End Sub
End Module
' The example displays output like the following:
'       Task #10 created at 635116418427727841 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427727841 on thread #3.
'       Task #10 created at 635116418427747843 on thread #3.
'       Task #10 created at 635116418427747843 on thread #3.
'       Task #10 created at 635116418427737842 on thread #4.

K hodnotě v každé iteraci můžete přistupovat zadáním objektu stavu úlohy pomocí jeho konstruktoru.You can access the value on each iteration by providing a state object to a task through its constructor. Následující příklad upravuje předchozí příklad pomocí čítače smyčky při vytváření objektu CustomData, který je zase předán výrazu lambda.The following example modifies the previous example by using the loop counter when creating the CustomData object, which, in turn, is passed to the lambda expression. Jak výstup z příkladu ukazuje, každý objekt CustomData nyní má jedinečný identifikátor na základě hodnoty čítače smyčky v době, kdy byla vytvořena instance objektu.As the output from the example shows, each CustomData object now has a unique identifier based on the value of the loop counter at the time the object was instantiated.

using System;
using System.Threading;
using System.Threading.Tasks;

class CustomData
{
   public long CreationTime;
   public int Name; 
   public int ThreadNum;
}

public class Example
{
   public static void Main()
   {
      // Create the task object by using an Action(Of Object) to pass in custom data
      // to the Task constructor. This is useful when you need to capture outer variables
      // from within a loop. 
      Task[] taskArray = new Task[10];
      for (int i = 0; i < taskArray.Length; i++) {
         taskArray[i] = Task.Factory.StartNew( (Object obj ) => {
                                                  CustomData data = obj as CustomData;
                                                  if (data == null) 
                                                     return;
                                     
                                                  data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
                                                  Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
                                                                   data.Name, data.CreationTime, data.ThreadNum);
                                               },
                                               new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks} );
      }
      Task.WaitAll(taskArray);     
   }
}
// The example displays output like the following:
//       Task #0 created at 635116412924597583 on thread #3.
//       Task #1 created at 635116412924607584 on thread #4.
//       Task #3 created at 635116412924607584 on thread #4.
//       Task #4 created at 635116412924607584 on thread #4.
//       Task #2 created at 635116412924607584 on thread #3.
//       Task #6 created at 635116412924607584 on thread #3.
//       Task #5 created at 635116412924607584 on thread #4.
//       Task #8 created at 635116412924607584 on thread #4.
//       Task #7 created at 635116412924607584 on thread #3.
//       Task #9 created at 635116412924607584 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks

Class CustomData
   Public CreationTime As Long
   Public Name As Integer
   Public ThreadNum As Integer
End Class

Module Example
   Public Sub Main()
      ' Create the task object by using an Action(Of Object) to pass in custom data
      ' to the Task constructor. This is useful when you need to capture outer variables
      ' from within a loop. 
      Dim taskArray(9) As Task
      For i As Integer = 0 To taskArray.Length - 1
         taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
                                                 Dim data As CustomData = TryCast(obj, CustomData)
                                                 If data Is Nothing Then Return
                                     
                                                 data.ThreadNum = Thread.CurrentThread.ManagedThreadId
                                                 Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
                                                                   data.Name, data.CreationTime, data.ThreadNum)
                                              End Sub,
                                              New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks} )
      Next
      Task.WaitAll(taskArray)     
   End Sub
End Module
' The example displays output like the following:
'       Task #0 created at 635116412924597583 on thread #3.
'       Task #1 created at 635116412924607584 on thread #4.
'       Task #3 created at 635116412924607584 on thread #4.
'       Task #4 created at 635116412924607584 on thread #4.
'       Task #2 created at 635116412924607584 on thread #3.
'       Task #6 created at 635116412924607584 on thread #3.
'       Task #5 created at 635116412924607584 on thread #4.
'       Task #8 created at 635116412924607584 on thread #4.
'       Task #7 created at 635116412924607584 on thread #3.
'       Task #9 created at 635116412924607584 on thread #4.

Tento stav je předán jako argument delegátu úlohy a lze k němu přistupovat z objektu úlohy pomocí vlastnosti Task.AsyncState.This state is passed as an argument to the task delegate, and it can be accessed from the task object by using the Task.AsyncState property. Následující příklad je podobný předchozímu příkladu.The following example is a variation on the previous example. Používá vlastnost AsyncState k zobrazení informací o objektech CustomData předaných do výrazu lambda.It uses the AsyncState property to display information about the CustomData objects passed to the lambda expression.

using System;
using System.Threading;
using System.Threading.Tasks;

class CustomData
{
   public long CreationTime;
   public int Name; 
   public int ThreadNum;
}

public class Example
{
   public static void Main()
   {
      Task[] taskArray = new Task[10];
      for (int i = 0; i < taskArray.Length; i++) {
         taskArray[i] = Task.Factory.StartNew( (Object obj ) => {
                                                  CustomData data = obj as CustomData;
                                                  if (data == null) 
                                                     return;
                                     
                                                  data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
                                               },
                                               new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks} );
      }
      Task.WaitAll(taskArray);     
      foreach (var task in taskArray) {
         var data = task.AsyncState as CustomData;
         if (data != null)
            Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
                              data.Name, data.CreationTime, data.ThreadNum);
      }                     
   }
}
// The example displays output like the following:
//       Task #0 created at 635116412924597583 on thread #3.
//       Task #1 created at 635116412924607584 on thread #4.
//       Task #3 created at 635116412924607584 on thread #4.
//       Task #4 created at 635116412924607584 on thread #4.
//       Task #2 created at 635116412924607584 on thread #3.
//       Task #6 created at 635116412924607584 on thread #3.
//       Task #5 created at 635116412924607584 on thread #4.
//       Task #8 created at 635116412924607584 on thread #4.
//       Task #7 created at 635116412924607584 on thread #3.
//       Task #9 created at 635116412924607584 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks

Class CustomData
   Public CreationTime As Long
   Public Name As Integer
   Public ThreadNum As Integer
End Class

Module Example
   Public Sub Main()
      Dim taskArray(9) As Task
      For i As Integer = 0 To taskArray.Length - 1
         taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
                                                 Dim data As CustomData = TryCast(obj, CustomData)
                                                 If data Is Nothing Then Return
                                     
                                                 data.ThreadNum = Thread.CurrentThread.ManagedThreadId
                                              End Sub,
                                              New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks} )
      Next
      Task.WaitAll(taskArray)     

      For Each task In taskArray
         Dim data = TryCast(task.AsyncState, CustomData)
         If data IsNot Nothing Then
            Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
                              data.Name, data.CreationTime, data.ThreadNum)
         End If
      Next
   End Sub
End Module
' The example displays output like the following:
'    Task #0 created at 635116451245250515, ran on thread #3, RanToCompletion
'    Task #1 created at 635116451245270515, ran on thread #4, RanToCompletion
'    Task #2 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #3 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #4 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #5 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #6 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #7 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #8 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #9 created at 635116451245270515, ran on thread #3, RanToCompletion

ID úkoluTask ID

Každý úkol obdrží celočíselný identifikátor ID, který ji jednoznačně identifikuje v doméně aplikace a je k němu možné přistupovat pomocí vlastnosti Task.Id.Every task receives an integer ID that uniquely identifies it in an application domain and can be accessed by using the Task.Id property. ID je užitečné pro zobrazení informací o úloze v oknech paralelní zásobníky a úlohy ladicího programu sady Visual Studio.The ID is useful for viewing task information in the Visual Studio debugger Parallel Stacks and Tasks windows. ID využívá líné vytváření, což znamená, že není vytvořeno, dokud se o něj nepožádá, proto může mít úloha při každém spuštění programu jiné ID.The ID is lazily created, which means that it isn't created until it is requested; therefore, a task may have a different ID every time the program is run. Další informace o tom, jak zobrazit ID úloh v ladicím programu, najdete v tématu použití okna úlohy a použití okna Paralelní zásobníky.For more information about how to view task IDs in the debugger, see Using the Tasks Window and Using the Parallel Stacks Window.

Možnosti vytvoření úlohyTask creation options

Většina rozhraní API, která vytvářejí úlohy, poskytují přetížení, která přijímají parametr TaskCreationOptions.Most APIs that create tasks provide overloads that accept a TaskCreationOptions parameter. Zadáním jedné z těchto možností lze dát pokyn plánovači úloh, jak naplánovat úlohy ve fondu vláken.By specifying one of these options, you tell the task scheduler how to schedule the task on the thread pool. V následující tabulce jsou uvedeny různé možnosti pro vytváření úloh.The following table lists the various task creation options.

hodnota parametru TaskCreationOptionsTaskCreationOptions parameter value PopisDescription
None Výchozí hodnota, pokud není zadána jiná.The default when no option is specified. Plánovač používá k plánování úlohy své výchozí heuristické metody.The scheduler uses its default heuristics to schedule the task.
PreferFairness Určuje, že úlohy by měly být naplánovány tak, aby se úlohy vytvořené dříve pravděpodobně prováděly dříve a později vytvořené úlohy aby se s větší pravděpodobností prováděly později.Specifies that the task should be scheduled so that tasks created sooner will be more likely to be executed sooner, and tasks created later will be more likely to execute later.
LongRunning Určuje, že úloha představuje dlouhotrvající operaci.Specifies that the task represents a long-running operation.
AttachedToParent Určuje, že úloha by měla být vytvořena jako připojená podřízená úloha aktuální úlohy, pokud existuje.Specifies that a task should be created as an attached child of the current task, if one exists. Další informace najdete v tématu připojené a odpojené podřízené úlohy.For more information, see Attached and Detached Child Tasks.
DenyChildAttach Určuje, že pokud vnitřní úloha Určuje možnost AttachedToParent, tato úloha se nestane připojenou podřízenou úlohou.Specifies that if an inner task specifies the AttachedToParent option, that task will not become an attached child task.
HideScheduler Určuje, že Plánovač úloh pro úlohy vytvořené voláním metod, jako je TaskFactory.StartNew nebo Task<TResult>.ContinueWith z konkrétního úkolu, je výchozím plánovačem namísto plánovače, na kterém je tato úloha spuštěná.Specifies that the task scheduler for tasks created by calling methods like TaskFactory.StartNew or Task<TResult>.ContinueWith from within a particular task is the default scheduler instead of the scheduler on which this task is running.

Možnosti lze kombinovat pomocí bitové operace nebo .The options may be combined by using a bitwise OR operation. Následující příklad ukazuje úlohu s možností LongRunning a PreferFairness.The following example shows a task that has the LongRunning and PreferFairness option.

var task3 = new Task(() => MyLongRunningMethod(),
                    TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
task3.Start();

Dim task3 = New Task(Sub() MyLongRunningMethod(),
                        TaskCreationOptions.LongRunning Or TaskCreationOptions.PreferFairness)
task3.Start()

Úlohy, vlákna a jazyková verzeTasks, threads, and culture

Každé vlákno má přidruženou jazykovou verzi a jazykovou verzi uživatelského rozhraní, které je definováno Thread.CurrentCulture a Thread.CurrentUICulture vlastností, v uvedeném pořadí.Each thread has an associated culture and UI culture, which is defined by the Thread.CurrentCulture and Thread.CurrentUICulture properties, respectively. Jazyková verze vlákna se v takových operacích používá jako formátování, analýza, řazení a porovnávání řetězců.A thread's culture is used in such operations as formatting, parsing, sorting, and string comparison. Jazyková verze uživatelského rozhraní vlákna se používá při vyhledávání prostředků.A thread's UI culture is used in resource lookup. Pokud nezadáte výchozí jazykovou verzi pro všechna vlákna v doméně aplikace pomocí vlastností CultureInfo.DefaultThreadCurrentCulture a CultureInfo.DefaultThreadCurrentUICulture, je výchozí jazyková verze a jazyková verze uživatelského rozhraní definovaná jazykovou verzí systému.Ordinarily, unless you specify a default culture for all the threads in an application domain by using the CultureInfo.DefaultThreadCurrentCulture and CultureInfo.DefaultThreadCurrentUICulture properties, the default culture and UI culture of a thread is defined by the system culture. Pokud jste explicitně nastavili jazykovou verzi vlákna a spustili nové vlákno, nové vlákno nedědí jazykovou verzi volajícího vlákna; místo toho je jeho jazyková verze výchozí jazyková verze systému.If you explicitly set a thread's culture and launch a new thread, the new thread does not inherit the culture of the calling thread; instead, its culture is the default system culture. Programovací model založený na úlohách pro aplikace, které cílí na verze .NET Framework před .NET Framework 4,6 v souladu s tímto postupem.The task-based programming model for apps that target versions of the .NET Framework prior to .NET Framework 4.6 adhere to this practice.

Důležité

Všimněte si, že jazyková verze volajícího vlákna je v rámci kontextu úlohy platná pro aplikace, které cílí na .NET Framework 4,6, ne aplikace, které běží pod .NET Framework 4,6.Note that the calling thread's culture as part of a task's context applies to apps that target the .NET Framework 4.6, not apps that run under the .NET Framework 4.6. Můžete cílit na konkrétní verzi .NET Framework při vytváření projektu v aplikaci Visual Studio výběrem této verze z rozevíracího seznamu v horní části dialogového okna Nový projekt nebo mimo sadu Visual Studio můžete použít atribut TargetFrameworkAttribute.You can target a particular version of the .NET Framework when you create your project in Visual Studio by selecting that version from the dropdown list at the top of the New Project dialog box, or outside of Visual Studio you can use the TargetFrameworkAttribute attribute. Pro aplikace, které cílí na verze .NET Framework před .NET Framework 4,6 nebo které necílí na konkrétní verzi .NET Framework, je jazyková verze úlohy i nadále určena kulturou vlákna, na které běží.For apps that target versions of the .NET Framework prior to the .NET Framework 4.6, or that do not target a specific version of the .NET Framework, a task's culture continues to be determined by the culture of the thread on which it runs.

Počínaje aplikacemi, které cílí na .NET Framework 4,6, je jazyková verze volajícího vlákna zděděna každou úlohou, a to i v případě, že se úloha spouští asynchronně ve vlákně fondu vláken.Starting with apps that target the .NET Framework 4.6, the calling thread's culture is inherited by each task, even if the task runs asynchronously on a thread pool thread.

Následující příklad poskytuje jednoduchý obrázek.The following example provides a simple illustration. Používá atribut TargetFrameworkAttribute k cílení na .NET Framework 4,6 a změní aktuální jazykovou verzi aplikace na francouzštinu (Francie) nebo, pokud francouzština (Francie) je již aktuální jazykovou verzí, anglickou (USA).It uses the TargetFrameworkAttribute attribute to target the .NET Framework 4.6 and changes the app's current culture to either French (France) or, if French (France) is already the current culture, English (United States). Poté vyvolá delegáta s názvem formatDelegate, který vrátí čísla formátovaná jako hodnoty měny v nové jazykové verzi.It then invokes a delegate named formatDelegate that returns some numbers formatted as currency values in the new culture. Všimněte si, zda delegát jako úkol buď synchronně, nebo asynchronně, vrátí očekávaný výsledek, protože jazyková verze volajícího vlákna je zděděna asynchronním úkolem.Note that whether the delegate as a task either synchronously or asynchronously, it returns the expected result because the culture of the calling thread is inherited by the asynchronous task.

using System;
using System.Globalization;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;

[assembly:TargetFramework(".NETFramework,Version=v4.6")]

public class Example
{
   
   public static void Main()
   {
       decimal[] values = { 163025412.32m, 18905365.59m };
       string formatString = "C2";
       Func<String> formatDelegate = () => { string output = String.Format("Formatting using the {0} culture on thread {1}.\n",
                                                                           CultureInfo.CurrentCulture.Name,
                                                                           Thread.CurrentThread.ManagedThreadId);
                                             foreach (var value in values)
                                                output += String.Format("{0}   ", value.ToString(formatString));
                                                   
                                             output += Environment.NewLine;
                                             return output;
                                           };
       
       Console.WriteLine("The example is running on thread {0}", 
                         Thread.CurrentThread.ManagedThreadId);
       // Make the current culture different from the system culture.
       Console.WriteLine("The current culture is {0}", 
                         CultureInfo.CurrentCulture.Name);
       if (CultureInfo.CurrentCulture.Name == "fr-FR")
          Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
       else
          Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");

       Console.WriteLine("Changed the current culture to {0}.\n",
                         CultureInfo.CurrentCulture.Name);
       
       // Execute the delegate synchronously.
       Console.WriteLine("Executing the delegate synchronously:");
       Console.WriteLine(formatDelegate());
       
       // Call an async delegate to format the values using one format string.
       Console.WriteLine("Executing a task asynchronously:"); 
       var t1 = Task.Run(formatDelegate);
       Console.WriteLine(t1.Result);
       
       Console.WriteLine("Executing a task synchronously:");
       var t2 = new Task<String>(formatDelegate); 
       t2.RunSynchronously();
       Console.WriteLine(t2.Result);
   }
}
// The example displays the following output:
//         The example is running on thread 1
//         The current culture is en-US
//         Changed the current culture to fr-FR.
//
//         Executing the delegate synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task asynchronously:
//         Formatting using the fr-FR culture on thread 3.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €
// If the TargetFrameworkAttribute statement is removed, the example
// displays the following output:
//          The example is running on thread 1
//          The current culture is en-US
//          Changed the current culture to fr-FR.
//
//          Executing the delegate synchronously:
//          Formatting using the fr-FR culture on thread 1.
//          163 025 412,32 €   18 905 365,59 €
//
//          Executing a task asynchronously:
//          Formatting using the en-US culture on thread 3.
//          $163,025,412.32   $18,905,365.59
//
//          Executing a task synchronously:
//          Formatting using the fr-FR culture on thread 1.
//          163 025 412,32 €   18 905 365,59 €
Imports System.Globalization
Imports System.Runtime.Versioning
Imports System.Threading
Imports System.Threading.Tasks

<Assembly:TargetFramework(".NETFramework,Version=v4.6")>

Module Example
   Public Sub Main()
       Dim values() As Decimal = { 163025412.32d, 18905365.59d }
       Dim formatString As String = "C2"
       Dim formatDelegate As Func(Of String) = Function()
                                                  Dim output As String = String.Format("Formatting using the {0} culture on thread {1}.",
                                                                                       CultureInfo.CurrentCulture.Name,
                                                                                       Thread.CurrentThread.ManagedThreadId)
                                                  output += Environment.NewLine
                                                  For Each value In values
                                                     output += String.Format("{0}   ", value.ToString(formatString))
                                                  Next 
                                                  output += Environment.NewLine
                                                  Return output
                                               End Function
       
       Console.WriteLine("The example is running on thread {0}", 
                         Thread.CurrentThread.ManagedThreadId)
       ' Make the current culture different from the system culture.
       Console.WriteLine("The current culture is {0}", 
                         CultureInfo.CurrentCulture.Name)
       If CultureInfo.CurrentCulture.Name = "fr-FR" Then
          Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
       Else
          Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR")
       End If
       Console.WriteLine("Changed the current culture to {0}.",
                         CultureInfo.CurrentCulture.Name)
       Console.WriteLine()                  
       
       ' Execute the delegate synchronously.
       Console.WriteLine("Executing the delegate synchronously:")
       Console.WriteLine(formatDelegate())
       
       ' Call an async delegate to format the values using one format string.
       Console.WriteLine("Executing a task asynchronously:") 
       Dim t1 = Task.Run(formatDelegate)
       Console.WriteLine(t1.Result)
       
       Console.WriteLine("Executing a task synchronously:")
       Dim t2 = New Task(Of String)(formatDelegate) 
       t2.RunSynchronously()
       Console.WriteLine(t2.Result)
   End Sub
End Module
' The example displays the following output:
'          The example is running on thread 1
'          The current culture is en-US
'          Changed the current culture to fr-FR.
'
'          Executing the delegate synchronously:
'          Formatting Imports the fr-FR culture on thread 1.
'          163 025 412,32 €   18 905 365,59 €
'
'          Executing a task asynchronously:
'          Formatting Imports the fr-FR culture on thread 3.
'          163 025 412,32 €   18 905 365,59 €
'
'          Executing a task synchronously:
'          Formatting Imports the fr-FR culture on thread 1.
'          163 025 412,32 €   18 905 365,59 €
' If the TargetFrameworkAttribute statement is removed, the example
' displays the following output:
'          The example is running on thread 1
'          The current culture is en-US
'          Changed the current culture to fr-FR.
'
'          Executing the delegate synchronously:
'          Formatting using the fr-FR culture on thread 1.
'          163 025 412,32 €   18 905 365,59 €
'
'          Executing a task asynchronously:
'          Formatting using the en-US culture on thread 3.
'          $163,025,412.32   $18,905,365.59
'
'          Executing a task synchronously:
'          Formatting using the fr-FR culture on thread 1.
'          163 025 412,32 €   18 905 365,59 €

Pokud používáte aplikaci Visual Studio, můžete vynechat atribut TargetFrameworkAttribute a místo toho vybrat .NET Framework 4,6 jako cíl při vytváření projektu v dialogovém okně Nový projekt .If you are using Visual Studio, you can omit the TargetFrameworkAttribute attribute and instead select the .NET Framework 4.6 as the target when you create the project in the New Project dialog.

Pro výstup, který odráží chování aplikací cílové verze .NET Framework před .NET Framework 4,6, odeberte atribut TargetFrameworkAttribute ze zdrojového kódu.For output that reflects the behavior of apps the target versions of the .NET Framework prior to .NET Framework 4.6, remove the TargetFrameworkAttribute attribute from the source code. Výstup bude odpovídat konvencím formátování výchozí jazykové verze systému, nikoli jazykové verzi volajícího vlákna.The output will reflect the formatting conventions of the default system culture, not the culture of the calling thread.

Další informace o asynchronních úlohách a jazykové verzi naleznete v části "jazyková verze a asynchronní operace založené na úlohách" v tématu CultureInfo.For more information on asynchronous tasks and culture, see the "Culture and asynchronous task-based operations" section in the CultureInfo topic.

Vytváření pokračování úlohyCreating task continuations

Metody Task.ContinueWith a Task<TResult>.ContinueWith umožňují určit úlohu, která se spustí po dokončení předchozí úlohy .The Task.ContinueWith and Task<TResult>.ContinueWith methods let you specify a task to start when the antecedent task finishes. Delegátem úlohy pokračování je předán odkaz na předchozí úlohu, aby mohl prověřit stav předchozí úlohy a načtením hodnoty vlastnosti Task<TResult>.Result může použít výstup předchůdce jako vstup pro pokračování.The delegate of the continuation task is passed a reference to the antecedent task so that it can examine the antecedent task's status and, by retrieving the value of the Task<TResult>.Result property, can use the output of the antecedent as input for the continuation.

V následujícím příkladu je úloha getData spuštěna voláním metody TaskFactory.StartNew<TResult>(Func<TResult>).In the following example, the getData task is started by a call to the TaskFactory.StartNew<TResult>(Func<TResult>) method. Úloha processData se spustí automaticky po dokončení getData a po dokončení processData se spustí displayData.The processData task is started automatically when getData finishes, and displayData is started when processData finishes. getData vytváří celočíselné pole, které je přístupné processData úloze prostřednictvím vlastnosti Task<TResult>.Result úkolu getData.getData produces an integer array, which is accessible to the processData task through the getData task's Task<TResult>.Result property. Úloha processData zpracuje toto pole a vrátí výsledek, jehož typ je odvozen z návratového typu výrazu lambda, který byl předán metodě Task<TResult>.ContinueWith<TNewResult>(Func<Task<TResult>,TNewResult>).The processData task processes that array and returns a result whose type is inferred from the return type of the lambda expression passed to the Task<TResult>.ContinueWith<TNewResult>(Func<Task<TResult>,TNewResult>) method. Úloha displayData se spustí automaticky po dokončení processData a objekt Tuple<T1,T2,T3> vrácený processData výraz lambda je přístupný displayData úloze prostřednictvím vlastnosti processData úkolu Task<TResult>.Result.The displayData task executes automatically when processData finishes, and the Tuple<T1,T2,T3> object returned by the processData lambda expression is accessible to the displayData task through the processData task's Task<TResult>.Result property. Úloha displayData přebírá výsledek úlohy processData a vytváří výsledek, jehož typ je odvozen podobným způsobem a který je zpřístupněn programu ve vlastnosti Result.The displayData task takes the result of the processData task and produces a result whose type is inferred in a similar manner and which is made available to the program in the Result property.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {                         
      var getData = Task.Factory.StartNew(() => { 
                                             Random rnd = new Random(); 
                                             int[] values = new int[100];
                                             for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
                                                values[ctr] = rnd.Next();

                                             return values;
                                          } );  
      var processData = getData.ContinueWith((x) => {
                                                int n = x.Result.Length;
                                                long sum = 0;
                                                double mean;
                                  
                                                for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)
                                                   sum += x.Result[ctr];

                                                mean = sum / (double) n;
                                                return Tuple.Create(n, sum, mean);
                                             } ); 
      var displayData = processData.ContinueWith((x) => {
                                                    return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                                         x.Result.Item1, x.Result.Item2, 
                                                                         x.Result.Item3);
                                                 } );                         
      Console.WriteLine(displayData.Result);
   }
}
// The example displays output similar to the following:
//    N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim getData = Task.Factory.StartNew(Function() 
                                             Dim rnd As New Random()
                                             Dim values(99) As Integer
                                             For ctr = 0 To values.GetUpperBound(0)
                                                values(ctr) = rnd.Next()
                                             Next
                                             Return values
                                          End Function)  
      Dim processData = getData.ContinueWith(Function(x)
                                                Dim n As Integer = x.Result.Length
                                                Dim sum As Long
                                                Dim mean As Double
                                  
                                                For ctr = 0 To x.Result.GetUpperBound(0)
                                                   sum += x.Result(ctr)
                                                Next
                                                mean = sum / n
                                                Return Tuple.Create(n, sum, mean)
                                             End Function) 
      Dim displayData = processData.ContinueWith(Function(x)
                                                    Return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                                         x.Result.Item1, x.Result.Item2, 
                                                                         x.Result.Item3)
                                                 End Function)                         
      Console.WriteLine(displayData.Result)
   End Sub                        
End Module
' The example displays output like the following:
'   N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82

Vzhledem k tomu, že Task.ContinueWith je metoda instance, můžete zřetězit volání metody společně namísto vytvoření instance Task<TResult> objektu pro každou předchozí úlohu.Because Task.ContinueWith is an instance method, you can chain method calls together instead of instantiating a Task<TResult> object for each antecedent task. Následující příklad je funkčně totožný s předchozím příkladem, s tím rozdílem, že řetězí volání metody Task.ContinueWith.The following example is functionally identical to the previous example, except that it chains together calls to the Task.ContinueWith method. Všimněte si, že objekt Task<TResult> vrácený řetězcem volání metody je konečný úkol pokračování.Note that the Task<TResult> object returned by the chain of method calls is the final continuation task.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {                         
      var displayData = Task.Factory.StartNew(() => { 
                                                 Random rnd = new Random(); 
                                                 int[] values = new int[100];
                                                 for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
                                                    values[ctr] = rnd.Next();

                                                 return values;
                                              } ).  
                        ContinueWith((x) => {
                                        int n = x.Result.Length;
                                        long sum = 0;
                                        double mean;
                                  
                                        for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)
                                           sum += x.Result[ctr];

                                        mean = sum / (double) n;
                                        return Tuple.Create(n, sum, mean);
                                     } ). 
                        ContinueWith((x) => {
                                        return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                             x.Result.Item1, x.Result.Item2, 
                                                             x.Result.Item3);
                                     } );                         
      Console.WriteLine(displayData.Result);
   }
}
// The example displays output similar to the following:
//    N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim displayData = Task.Factory.StartNew(Function() 
                                                 Dim rnd As New Random()
                                                 Dim values(99) As Integer
                                                 For ctr = 0 To values.GetUpperBound(0)
                                                    values(ctr) = rnd.Next()
                                                 Next
                                                 Return values
                                              End Function). _  
                        ContinueWith(Function(x)
                                        Dim n As Integer = x.Result.Length
                                        Dim sum As Long
                                        Dim mean As Double
                                  
                                        For ctr = 0 To x.Result.GetUpperBound(0)
                                           sum += x.Result(ctr)
                                        Next
                                        mean = sum / n
                                        Return Tuple.Create(n, sum, mean)
                                     End Function). _ 
                        ContinueWith(Function(x)
                                        Return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                             x.Result.Item1, x.Result.Item2,  
                                                             x.Result.Item3)
                                     End Function)                         
      Console.WriteLine(displayData.Result)
   End Sub                        
End Module
' The example displays output like the following:
'   N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82

Metody ContinueWhenAll a ContinueWhenAny umožňují pokračovat z více úloh.The ContinueWhenAll and ContinueWhenAny methods enable you to continue from multiple tasks.

Další informace najdete v tématu zřetězení úloh pomocí úloh pokračování.For more information, see Chaining Tasks by Using Continuation Tasks.

Vytváření odpojených podřízených úlohCreating detached child tasks

Když uživatelský kód, který běží v rámci úlohy, vytvoří novou úlohu a neurčí možnost AttachedToParent, není nová úloha žádným zvláštním způsobem synchronizována s nadřazenou úlohou.When user code that is running in a task creates a new task and does not specify the AttachedToParent option, the new task is not synchronized with the parent task in any special way. Tento typ nesynchronizované úlohy se nazývá odpojená vnořená úloha nebo odpojená podřízená úloha.This type of non-synchronized task is called a detached nested task or detached child task. Následující příklad zobrazuje úlohu, která vytváří jednu odpojenou podřízenou úlohu.The following example shows a task that creates one detached child task.

var outer = Task.Factory.StartNew(() =>
{
    Console.WriteLine("Outer task beginning.");

    var child = Task.Factory.StartNew(() =>
    {
        Thread.SpinWait(5000000);
        Console.WriteLine("Detached task completed.");
    });

});

outer.Wait();
Console.WriteLine("Outer task completed.");
// The example displays the following output:
//    Outer task beginning.
//    Outer task completed.
//    Detached task completed.
Dim outer = Task.Factory.StartNew(Sub()
                                      Console.WriteLine("Outer task beginning.")
                                      Dim child = Task.Factory.StartNew(Sub()
                                                                            Thread.SpinWait(5000000)
                                                                            Console.WriteLine("Detached task completed.")
                                                                        End Sub)
                                  End Sub)
outer.Wait()
Console.WriteLine("Outer task completed.")
' The example displays the following output:
'     Outer task beginning.
'     Outer task completed.
'    Detached child completed.

Nadřazená úloha nečeká na dokončení odpojené podřízené úlohy.Note that the parent task does not wait for the detached child task to finish.

Vytváření podřízených úlohCreating child tasks

Když uživatelský kód, který běží v rámci úlohy, vytvoří úlohu s možností AttachedToParent, je nová úloha známá jako připojená podřízená úloha nadřazené úlohy.When user code that is running in a task creates a task with the AttachedToParent option, the new task is known as a attached child task of the parent task. Možnost AttachedToParent můžete použít k vyjádření strukturovaného paralelismu úloh, protože nadřazená úloha implicitně čeká na dokončení všech připojených podřízených úloh.You can use the AttachedToParent option to express structured task parallelism, because the parent task implicitly waits for all attached child tasks to finish. Následující příklad zobrazuje nadřazenou úlohu, která vytvoří deset připojených podřízených úloh.The following example shows a parent task that creates ten attached child tasks. Všimněte si, že přestože příklad volá metodu Task.Wait pro čekání na dokončení nadřazené úlohy, nemusí explicitně čekat na dokončení připojených podřízených úloh.Note that although the example calls the Task.Wait method to wait for the parent task to finish, it does not have to explicitly wait for the attached child tasks to complete.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var parent = Task.Factory.StartNew(() => {
                      Console.WriteLine("Parent task beginning.");
                      for (int ctr = 0; ctr < 10; ctr++) {
                         int taskNo = ctr;
                         Task.Factory.StartNew((x) => {
                                                  Thread.SpinWait(5000000);
                                                  Console.WriteLine("Attached child #{0} completed.", 
                                                                    x);
                                               },
                                               taskNo, TaskCreationOptions.AttachedToParent);
                      }
                   });

      parent.Wait();
      Console.WriteLine("Parent task completed.");
   }
}
// The example displays output like the following:
//       Parent task beginning.
//       Attached child #9 completed.
//       Attached child #0 completed.
//       Attached child #8 completed.
//       Attached child #1 completed.
//       Attached child #7 completed.
//       Attached child #2 completed.
//       Attached child #6 completed.
//       Attached child #3 completed.
//       Attached child #5 completed.
//       Attached child #4 completed.
//       Parent task completed.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim parent = Task.Factory.StartNew(Sub()
                                            Console.WriteLine("Parent task beginning.")
                                            For ctr As Integer = 0 To 9
                                               Dim taskNo As Integer = ctr
                                               Task.Factory.StartNew(Sub(x)
                                                                        Thread.SpinWait(5000000)
                                                                        Console.WriteLine("Attached child #{0} completed.", 
                                                                                          x)
                                                                     End Sub,
                                                                     taskNo, TaskCreationOptions.AttachedToParent)
                                            Next
                                         End Sub)
      parent.Wait()
      Console.WriteLine("Parent task completed.")
   End Sub
End Module   
' The example displays output like the following:
'       Parent task beginning.
'       Attached child #9 completed.
'       Attached child #0 completed.
'       Attached child #8 completed.
'       Attached child #1 completed.
'       Attached child #7 completed.
'       Attached child #2 completed.
'       Attached child #6 completed.
'       Attached child #3 completed.
'       Attached child #5 completed.
'       Attached child #4 completed.
'       Parent task completed.

Nadřazený úkol může použít možnost TaskCreationOptions.DenyChildAttach, aby se zabránilo připojení jiných úloh k nadřazené úloze.A parent task can use the TaskCreationOptions.DenyChildAttach option to prevent other tasks from attaching to the parent task. Další informace najdete v tématu připojené a odpojené podřízené úlohy.For more information, see Attached and Detached Child Tasks.

Čeká se na dokončení úloh.Waiting for tasks to finish

Typy System.Threading.Tasks.Task a System.Threading.Tasks.Task<TResult> poskytují několik přetížení Task.Waitch metod, které umožňují počkat na dokončení úlohy.The System.Threading.Tasks.Task and System.Threading.Tasks.Task<TResult> types provide several overloads of the Task.Wait methods that enable you to wait for a task to finish. Kromě toho přetížení statických Task.WaitAll a metod Task.WaitAny umožňují počkat na dokončení všech nebo všech polí úkolů.In addition, overloads of the static Task.WaitAll and Task.WaitAny methods let you wait for any or all of an array of tasks to finish.

Obvykle se na úlohu čeká z některého z těchto důvodů:Typically, you would wait for a task for one of these reasons:

  • Hlavní vlákno závisí na konečném výsledku vypočítaném úlohou.The main thread depends on the final result computed by a task.

  • Je potřeba zpracovat výjimky, které mohou být vyvolány z úlohy.You have to handle exceptions that might be thrown from the task.

  • Aplikace se může ukončit předtím, než se dokončí všechny úlohy.The application may terminate before all tasks have completed execution. Například konzolové aplikace budou ukončeny co nejdříve po provedení veškerého synchronního kódu v Main (vstupní bod aplikace).For example, console applications will terminate as soon as all synchronous code in Main (the application entry point) has executed.

Následující příklad zobrazuje základní vzor, který nezahrnuje zpracování výjimek.The following example shows the basic pattern that does not involve exception handling.

Task[] tasks = new Task[3]
{
    Task.Factory.StartNew(() => MethodA()),
    Task.Factory.StartNew(() => MethodB()),
    Task.Factory.StartNew(() => MethodC())
};

//Block until all tasks complete.
Task.WaitAll(tasks);

// Continue on this thread...
Dim tasks() =
{
    Task.Factory.StartNew(Sub() MethodA()),
    Task.Factory.StartNew(Sub() MethodB()),
    Task.Factory.StartNew(Sub() MethodC())
}

' Block until all tasks complete.
Task.WaitAll(tasks)

' Continue on this thread...

Příklad zobrazující zpracování výjimek naleznete v tématu zpracování výjimek.For an example that shows exception handling, see Exception Handling.

Některá přetížení umožňují určit časový limit a jiné CancellationToken jako vstupní parametr, aby bylo možné samotné čekání zrušit buď programově, nebo jako odpověď na uživatelský vstup.Some overloads let you specify a time-out, and others take an additional CancellationToken as an input parameter, so that the wait itself can be canceled either programmatically or in response to user input.

Při čekání na úlohu se implicitně čeká na všechny podřízené položky této úlohy, které byly vytvořeny pomocí možnosti TaskCreationOptions.AttachedToParent.When you wait for a task, you implicitly wait for all children of that task that were created by using the TaskCreationOptions.AttachedToParent option. Task.Wait vrátí hodnotu okamžitě, pokud úloha již byla dokončena.Task.Wait returns immediately if the task has already completed. Jakékoli výjimky vyvolané úlohou budou vyvolány metodou Task.Wait, a to i v případě, že byla metoda Task.Wait volána po dokončení úlohy.Any exceptions raised by a task will be thrown by a Task.Wait method, even if the Task.Wait method was called after the task completed.

Vytváření úlohComposing tasks

Třídy Task a Task<TResult> poskytují několik metod, které vám pomohou vytvořit více úkolů pro implementaci běžných vzorů a lépe využívat funkce asynchronního jazyka, které jsou k C#dispozici v, F#Visual Basic a.The Task and Task<TResult> classes provide several methods that can help you compose multiple tasks to implement common patterns and to better use the asynchronous language features that are provided by C#, Visual Basic, and F#. Tato část popisuje metody WhenAll, WhenAny, Delaya FromResult.This section describes the WhenAll, WhenAny, Delay, and FromResult methods.

Task.WhenAllTask.WhenAll

Metoda Task.WhenAll asynchronně čeká na dokončení více objektů Task nebo Task<TResult>.The Task.WhenAll method asynchronously waits for multiple Task or Task<TResult> objects to finish. Poskytuje přetížené verze, které umožňují čekání na nerovnoměrné sady úloh.It provides overloaded versions that enable you to wait for non-uniform sets of tasks. Můžete například počkat na dokončení více Task a Task<TResult> objektů z jednoho volání metody.For example, you can wait for multiple Task and Task<TResult> objects to complete from one method call.

Task.WhenAnyTask.WhenAny

Metoda Task.WhenAny asynchronně čeká na dokončení jednoho z více objektů Task nebo Task<TResult>.The Task.WhenAny method asynchronously waits for one of multiple Task or Task<TResult> objects to finish. Stejně jako v metodě Task.WhenAll poskytuje tato metoda přetížené verze, které umožňují počkat na nejednotné sady úloh.As in the Task.WhenAll method, this method provides overloaded versions that enable you to wait for non-uniform sets of tasks. Metoda WhenAny je obzvláště užitečná v následujících scénářích.The WhenAny method is especially useful in the following scenarios.

  • Nadbytečné operace.Redundant operations. Zvažte algoritmus nebo operaci, které lze provést mnoha způsoby.Consider an algorithm or operation that can be performed in many ways. Můžete použít metodu WhenAny k výběru operace, která skončí jako první, a pak zrušit zbývající operace.You can use the WhenAny method to select the operation that finishes first and then cancel the remaining operations.

  • Prokládané operace.Interleaved operations. Můžete spustit více operací, které se musí dokončit, a použít metodu WhenAny ke zpracování výsledků při dokončení každé operace.You can start multiple operations that must all finish and use the WhenAny method to process results as each operation finishes. Po dokončení jedné operace můžete spustit jednu nebo více dalších úloh.After one operation finishes, you can start one or more additional tasks.

  • Omezené operace.Throttled operations. Můžete použít metodu WhenAny k prodloužení předchozího scénáře tím, že omezíte počet souběžných operací.You can use the WhenAny method to extend the previous scenario by limiting the number of concurrent operations.

  • Operace, jejichž platnost vypršela.Expired operations. Můžete použít metodu WhenAny k výběru jedné nebo více úloh a úlohy, která skončí po určitou dobu, například úlohy, která je vrácena metodou Delay.You can use the WhenAny method to select between one or more tasks and a task that finishes after a specific time, such as a task that is returned by the Delay method. Delay metoda je popsána v následující části.The Delay method is described in the following section.

Task.DelayTask.Delay

Metoda Task.Delay vytvoří objekt Task, který skončí po specifikovaném čase.The Task.Delay method produces a Task object that finishes after the specified time. Tuto metodu můžete použít k vytvoření cyklů, které občas provádějí dotazování na data, zavedení limitů, zpracování vstupu uživatele na předem stanovenou dobu zpoždění a tak dále.You can use this method to build loops that occasionally poll for data, introduce time-outs, delay the handling of user input for a predetermined time, and so on.

Task(T).FromResultTask(T).FromResult

Pomocí metody Task.FromResult můžete vytvořit objekt Task<TResult>, který obsahuje předem vypočítaný výsledek.By using the Task.FromResult method, you can create a Task<TResult> object that holds a pre-computed result. Tato metoda je užitečná při provádění asynchronní operace, která vrací objekt Task<TResult> a výsledek tohoto objektu Task<TResult> již je vypočítán.This method is useful when you perform an asynchronous operation that returns a Task<TResult> object, and the result of that Task<TResult> object is already computed. Příklad, který používá FromResult k načtení výsledků asynchronních operací stažení, které jsou uloženy v mezipaměti, naleznete v tématu How to: Create předběžně počítané úkoly.For an example that uses FromResult to retrieve the results of asynchronous download operations that are held in a cache, see How to: Create Pre-Computed Tasks.

Zpracování výjimek v úloháchHandling exceptions in tasks

Pokud úkol vyvolá jednu nebo více výjimek, výjimky jsou zabaleny do výjimky AggregateException.When a task throws one or more exceptions, the exceptions are wrapped in an AggregateException exception. Tato výjimka je šířena zpět do vlákna, které se spojí s úlohou, což je obvykle vlákno, které čeká na dokončení úlohy nebo vlákno, které přistupuje k vlastnosti Result.That exception is propagated back to the thread that joins with the task, which is typically the thread that is waiting for the task to finish or the thread that accesses the Result property. Toto chování slouží k vynucení, aby při všech neošetřených výjimkách ve výchozím nastavení zásady rozhraní .NET Framework ukončily proces.This behavior serves to enforce the .NET Framework policy that all unhandled exceptions by default should terminate the process. Volající kód může zpracovávat výjimky pomocí kterékoli z následujících v try/blok catch:The calling code can handle the exceptions by using any of the following in a try/catch block:

Spojovací vlákno může také zpracovávat výjimky přístupem k vlastnosti Exception dříve, než je úloha uvolněna z paměti.The joining thread can also handle exceptions by accessing the Exception property before the task is garbage-collected. Přístupem k této vlastnosti nebude nezpracovaná výjimka spouštět chování šíření výjimky, které ukončí proces, když je objekt finalizován.By accessing this property, you prevent the unhandled exception from triggering the exception propagation behavior that terminates the process when the object is finalized.

Další informace o výjimkách a úlohách naleznete v tématu zpracování výjimek.For more information about exceptions and tasks, see Exception Handling.

Rušení úlohCanceling tasks

Třída Task podporuje kooperativní zrušení a je plně integrovaná s System.Threading.CancellationTokenSource a System.Threading.CancellationTokenmi třídami, které byly představeny v .NET Framework 4.The Task class supports cooperative cancellation and is fully integrated with the System.Threading.CancellationTokenSource and System.Threading.CancellationToken classes, which were introduced in the .NET Framework 4. Mnoho konstruktorů ve třídě System.Threading.Tasks.Task převezme objekt CancellationToken jako vstupní parametr.Many of the constructors in the System.Threading.Tasks.Task class take a CancellationToken object as an input parameter. Mnoho z StartNew a Run přetížení také zahrnuje parametr CancellationToken.Many of the StartNew and Run overloads also include a CancellationToken parameter.

Můžete vytvořit token a vystavit žádost o zrušení později pomocí třídy CancellationTokenSource.You can create the token, and issue the cancellation request at some later time, by using the CancellationTokenSource class. Předání tokenu Task jako argumentu a také odkazování na stejný token v uživatelském delegátu, který provádí reakci na žádost o zrušení.Pass the token to the Task as an argument, and also reference the same token in your user delegate, which does the work of responding to a cancellation request.

Další informace naleznete v tématu zrušení úlohy a Postup: zrušení úlohy a jejích podřízených objektů.For more information, see Task Cancellation and How to: Cancel a Task and Its Children.

Třída TaskFactoryThe TaskFactory class

Třída TaskFactory poskytuje statické metody, které zapouzdřují některé běžné vzory pro vytváření a spouštění úloh a pokračujících úloh.The TaskFactory class provides static methods that encapsulate some common patterns for creating and starting tasks and continuation tasks.

Výchozí TaskFactory může být k dispozici jako statická vlastnost třídy Task nebo třídy Task<TResult>.The default TaskFactory can be accessed as a static property on the Task class or Task<TResult> class. Můžete také vytvořit instanci TaskFactory přímo a určit různé možnosti, které zahrnují CancellationToken, TaskCreationOptions možnost, TaskContinuationOptions možnost nebo TaskScheduler.You can also instantiate a TaskFactory directly and specify various options that include a CancellationToken, a TaskCreationOptions option, a TaskContinuationOptions option, or a TaskScheduler. Jakékoli možnosti, které jsou zadány při vytváření továrny úloh, budou použity pro všechny úlohy, které vytvoří, pokud se Task nevytvoří pomocí výčtu TaskCreationOptions, v takovém případě možnosti úlohy přepíší tyto továrny úloh.Whatever options are specified when you create the task factory will be applied to all tasks that it creates, unless the Task is created by using the TaskCreationOptions enumeration, in which case the task's options override those of the task factory.

Úlohy bez delegátůTasks without delegates

V některých případech můžete chtít použít Task k zapouzdření některé asynchronní operace, kterou provádí externí komponenta namísto uživatelského delegáta.In some cases, you may want to use a Task to encapsulate some asynchronous operation that is performed by an external component instead of your own user delegate. Pokud je operace založena na vzoru Begin/End modelu asynchronního programování, můžete použít metody FromAsync.If the operation is based on the Asynchronous Programming Model Begin/End pattern, you can use the FromAsync methods. V takovém případě můžete použít objekt TaskCompletionSource<TResult> k zabalení operace do úlohy a získat tak některé z výhod Task programovatelnosti, například podporu pro šíření výjimek a pokračování.If that is not the case, you can use the TaskCompletionSource<TResult> object to wrap the operation in a task and thereby gain some of the benefits of Task programmability, for example, support for exception propagation and continuations. Další informace najdete v tématu TaskCompletionSource<TResult>.For more information, see TaskCompletionSource<TResult>.

Vlastní plánovačeCustom schedulers

Většina vývojářů aplikací nebo knihoven nezáleží na tom, na kterém procesoru je úloha spuštěna, jak synchronizuje svou práci s ostatními úkoly nebo jak je naplánována na System.Threading.ThreadPool.Most application or library developers do not care which processor the task runs on, how it synchronizes its work with other tasks, or how it is scheduled on the System.Threading.ThreadPool. Vyžadují pouze to, aby byly tyto úkony v hostitelském počítači prováděny tak efektivně, jak je to možné.They only require that it execute as efficiently as possible on the host computer. Pokud požadujete jemněji odstupňovanou kontrolu nad podrobnostmi plánování, Task Parallel Library umožňuje konfigurovat některá nastavení výchozího plánovače úloh a dokonce umožňuje zadat vlastní plánovač.If you require more fine-grained control over the scheduling details, the Task Parallel Library lets you configure some settings on the default task scheduler, and even lets you supply a custom scheduler. Další informace najdete v tématu TaskScheduler.For more information, see TaskScheduler.

TPL má několik nových veřejných typů, které jsou použitelné jak v situacích paralelního, tak i sekvenčního vykonávání.The TPL has several new public types that are useful in both parallel and sequential scenarios. Mezi ně patří několik bezpečných a škálovatelných tříd kolekcí v oboru názvů System.Collections.Concurrent a několik nových typů synchronizace, například System.Threading.Semaphore a System.Threading.ManualResetEventSlim, které jsou efektivnější než jejich předchůdci pro konkrétní druhy úloh.These include several thread-safe, fast and scalable collection classes in the System.Collections.Concurrent namespace, and several new synchronization types, for example, System.Threading.Semaphore and System.Threading.ManualResetEventSlim, which are more efficient than their predecessors for specific kinds of workloads. Další nové typy v .NET Framework 4, například System.Threading.Barrier a System.Threading.SpinLock, poskytují funkce, které v dřívějších verzích nebyly k dispozici.Other new types in the .NET Framework 4, for example, System.Threading.Barrier and System.Threading.SpinLock, provide functionality that was not available in earlier releases. Další informace najdete v tématu datové struktury pro paralelní programování.For more information, see Data Structures for Parallel Programming.

Vlastní typy úlohCustom task types

Doporučujeme Nedědit z System.Threading.Tasks.Task ani System.Threading.Tasks.Task<TResult>.We recommend that you do not inherit from System.Threading.Tasks.Task or System.Threading.Tasks.Task<TResult>. Místo toho doporučujeme použít vlastnost AsyncState k přidružení dalších dat nebo stavu k objektu Task nebo Task<TResult>.Instead, we recommend that you use the AsyncState property to associate additional data or state with a Task or Task<TResult> object. Můžete také použít rozšiřující metody k rozšíření funkcí Task a Task<TResult> třídy.You can also use extension methods to extend the functionality of the Task and Task<TResult> classes. Další informace o metodách rozšíření naleznete v tématu metody rozšíření a metody rozšíření.For more information about extension methods, see Extension Methods and Extension Methods.

Pokud musíte dědit z Task nebo Task<TResult>, nemůžete použít Runnebo třídy System.Threading.Tasks.TaskFactory, System.Threading.Tasks.TaskFactory<TResult>nebo System.Threading.Tasks.TaskCompletionSource<TResult> k vytvoření instancí vlastního typu úkolu, protože tyto mechanismy vytvářejí pouze Task a Task<TResult> objekty.If you must inherit from Task or Task<TResult>, you cannot use Run, or the System.Threading.Tasks.TaskFactory, System.Threading.Tasks.TaskFactory<TResult>, or System.Threading.Tasks.TaskCompletionSource<TResult> classes to create instances of your custom task type because these mechanisms create only Task and Task<TResult> objects. Kromě toho nemůžete použít mechanismy pokračování úloh, které jsou k dispozici Task, Task<TResult>, TaskFactorya TaskFactory<TResult> k vytvoření instancí vlastního typu úkolu, protože tyto mechanismy také vytváří pouze Task a Task<TResult> objekty.In addition, you cannot use the task continuation mechanisms that are provided by Task, Task<TResult>, TaskFactory, and TaskFactory<TResult> to create instances of your custom task type because these mechanisms also create only Task and Task<TResult> objects.

NázevTitle PopisDescription
Řetězení úloh pomocí úloh pokračováníChaining Tasks by Using Continuation Tasks Popisuje, jak fungují pokračování.Describes how continuations work.
Připojené a odpojené podřízené úlohyAttached and Detached Child Tasks Popisuje rozdíl mezi připojenými a odpojenými podřízenými úlohami.Describes the difference between attached and detached child tasks.
Zrušení úlohyTask Cancellation Popisuje podporu zrušení, která je integrována do objektu Task.Describes the cancellation support that is built into the Task object.
Zpracování výjimekException Handling Popisuje způsob zpracování výjimek v souběžných vláknech.Describes how exceptions on concurrent threads are handled.
Postupy: Použití algoritmu Parallel.Invoke k provádění paralelních operacíHow to: Use Parallel.Invoke to Execute Parallel Operations Popisuje, jak používat Invoke.Describes how to use Invoke.
Postupy: Vrácení hodnoty z úlohyHow to: Return a Value from a Task Popisuje, jak z úloh vracet hodnoty.Describes how to return values from tasks.
Postupy: Zrušení úlohy a podřízených elementůHow to: Cancel a Task and Its Children Popisuje, jak zrušit úlohy.Describes how to cancel tasks.
Postupy: Vytváření předvypočítaných úlohHow to: Create Pre-Computed Tasks Popisuje, jak použít metodu Task.FromResult k načtení výsledků asynchronních operací stažení, které jsou uloženy v mezipaměti.Describes how to use the Task.FromResult method to retrieve the results of asynchronous download operations that are held in a cache.
Postupy: Procházení binárního stromu s paralelními úlohamiHow to: Traverse a Binary Tree with Parallel Tasks Popisuje, jak použít úlohy k procházení binárního stromu.Describes how to use tasks to traverse a binary tree.
Postupy: Rozbalení vnořené úlohyHow to: Unwrap a Nested Task Ukazuje, jak použít metodu rozšíření Unwrap.Demonstrates how to use the Unwrap extension method.
Datový paralelismusData Parallelism Popisuje, jak pomocí For a ForEach vytvořit paralelní smyčky pro data.Describes how to use For and ForEach to create parallel loops over data.
Paralelní programováníParallel Programming Uzel nejvyšší úrovně pro paralelní programování rozhraní .NET Framework.Top level node for .NET Framework parallel programming.

Viz také:See also