Para ver el artículo en inglés, active la casilla Inglés. También puede ver el texto en inglés en una ventana emergente si pasa el puntero del mouse por el texto.
Traducción
Inglés

How to: Prevent a Child Task from Attaching to its Parent

.NET Framework (current version)
 

En este documento se muestra cómo evitar que una tarea secundaria adjunta a la tarea primaria. Evitar que una tarea secundaria adjunta a su elemento primario es útil cuando se llama a un componente escrito por terceros y que también utilice tareas. Por ejemplo, un componente de terceros que utiliza la opción de TaskCreationOptions.AttachedToParent de crear un objeto de Task o de Task<TResult> puede producir problemas en el código si es de ejecución prolongada o produce una excepción no controlada.

Ejemplo

El ejemplo siguiente se comparan los efectos de utilizar opciones predeterminadas a los efectos de evitar que una tarea secundaria adjunta al elemento primario. El ejemplo crea un objeto de Task que llama a una biblioteca de terceros que también utilice un objeto de Task . La biblioteca de otro fabricante utiliza la opción de AttachedToParent de crear el objeto de Task . La aplicación utiliza la opción de TaskCreationOptions.DenyChildAttach de crear la tarea primaria. Esta opción indica al tiempo de ejecución para quitar la especificación de AttachedToParent en tareas secundarias.

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

// Defines functionality that is provided by a third-party.
// In a real-world scenario, this would likely be provided
// in a separate code file or assembly.
namespace Contoso
{
   public class Widget
   {     
      public Task Run()
      {
         // Create a long-running task that is attached to the 
         // parent in the task hierarchy.
         return Task.Factory.StartNew(() =>
         {
            // Simulate a lengthy operation.
            Thread.Sleep(5000);

         }, TaskCreationOptions.AttachedToParent);
      }
   }
}

// Demonstrates how to prevent a child task from attaching to the parent.
class DenyChildAttach
{
   static void RunWidget(Contoso.Widget widget,
      TaskCreationOptions parentTaskOptions)
   {
      // Record the time required to run the parent
      // and child tasks.
      Stopwatch stopwatch = new Stopwatch();
      stopwatch.Start();

      Console.WriteLine("Starting widget as a background task...");

      // Run the widget task in the background.
      Task<Task> runWidget = Task.Factory.StartNew(() =>
         {
            Task widgetTask = widget.Run();

            // Perform other work while the task runs...
            Thread.Sleep(1000);

            return widgetTask;
         }, parentTaskOptions);

      // Wait for the parent task to finish.
      Console.WriteLine("Waiting for parent task to finish...");
      runWidget.Wait();
      Console.WriteLine("Parent task has finished. Elapsed time is {0} ms.", 
         stopwatch.ElapsedMilliseconds);

      // Perform more work...
      Console.WriteLine("Performing more work on the main thread...");
      Thread.Sleep(2000);
      Console.WriteLine("Elapsed time is {0} ms.", stopwatch.ElapsedMilliseconds);

      // Wait for the child task to finish.
      Console.WriteLine("Waiting for child task to finish...");
      runWidget.Result.Wait();
      Console.WriteLine("Child task has finished. Elapsed time is {0} ms.",
        stopwatch.ElapsedMilliseconds);
   }

   static void Main(string[] args)
   {
      Contoso.Widget w = new Contoso.Widget();

      // Perform the same operation two times. The first time, the operation
      // is performed by using the default task creation options. The second
      // time, the operation is performed by using the DenyChildAttach option
      // in the parent task.

      Console.WriteLine("Demonstrating parent/child tasks with default options...");
      RunWidget(w, TaskCreationOptions.None);

      Console.WriteLine();

      Console.WriteLine("Demonstrating parent/child tasks with the DenyChildAttach option...");
      RunWidget(w, TaskCreationOptions.DenyChildAttach);
   }
}

/* Sample output:
Demonstrating parent/child tasks with default options...
Starting widget as a background task...
Waiting for parent task to finish...
Parent task has finished. Elapsed time is 5014 ms.
Performing more work on the main thread...
Elapsed time is 7019 ms.
Waiting for child task to finish...
Child task has finished. Elapsed time is 7019 ms.

Demonstrating parent/child tasks with the DenyChildAttach option...
Starting widget as a background task...
Waiting for parent task to finish...
Parent task has finished. Elapsed time is 1007 ms.
Performing more work on the main thread...
Elapsed time is 3015 ms.
Waiting for child task to finish...
Child task has finished. Elapsed time is 5015 ms.
*/

Dado que una tarea primaria no finaliza hasta que todo el final secundario de tareas, una tarea secundaria de ejecución prolongada puede provocar la aplicación total para ejecutarse mal. En este ejemplo, cuando la aplicación utiliza las opciones predeterminadas de crear la tarea primaria, la tarea secundaria debe finalizar antes de que la tarea primaria finaliza. Cuando la aplicación utiliza la opción de TaskCreationOptions.DenyChildAttach , no está asociado al elemento secundario al elemento primario. Por consiguiente, la aplicación puede realizar el trabajo adicional después de que la tarea primaria finaliza y antes de que debe esperar la tarea secundaria finalice.

Compilar el código

Copie el código de ejemplo y péguelo en un proyecto de Visual Studio, o péguelo en un archivo denominado DenyChildAttach.cs (DenyChildAttach.vb para Visual Basic), y ejecutar el siguiente comando en una ventana de símbolo del sistema de Visual Studio.

Visual C#

csc.exe DenyChildAttach.cs

Visual Basic

vbc.exe DenyChildAttach.vb

Programación eficaz

 

Mostrar: