¿Le resultó útil esta página?
Sus comentarios sobre este contenido son muy importantes. Háganos saber su opinión.
¿Tiene comentarios adicionales?
Caracteres restantes: 1500
Cómo: Desencapsular una tarea anidada
Este artículo se tradujo de forma manual. Mueva el puntero sobre las frases del artículo para ver el texto original. Más información.
Traducción
Original

Cómo: Desencapsular una tarea anidada

Puede devolver una tarea de un método y esperar o continuar a partir de esa tarea, como se muestra en el siguiente ejemplo:


static Task<string> DoWorkAsync()
{
    return Task<String>.Factory.StartNew(() =>
    {
       //...
        return "Work completed.";
    });
}

static void StartTask()
{
    Task<String> t = DoWorkAsync();
    t.Wait();
    Console.WriteLine(t.Result);
}


En el ejemplo anterior, la propiedad Result es de tipo string (String en Visual Basic).

Sin embargo, en algunos casos le podría interesar crear una tarea dentro de otra y devolver la tarea anidada. En este caso, TResult de la tarea que incluye es, en sí misma, una tarea. En el siguiente ejemplo, la propiedad Result es Task<Task<string>> en C# o Task(Of Task(Of String)) en Visual Basic.


// Note the type of t and t2.
Task<Task<string>> t = Task.Factory.StartNew(() => DoWorkAsync());
Task<Task<string>> t2 = DoWorkAsync().ContinueWith((s) => DoMoreWorkAsync());

// Outputs: System.Threading.Tasks.Task`1[System.String]
Console.WriteLine(t.Result);


Aunque es posible escribir código para desempaquetar la tarea exterior y recuperar la tarea original y su propiedad Result, tal código no es fácil de escribir porque se deben controlar las excepciones y también las solicitudes de cancelación. En esta situación, recomendamos utilizar uno de los métodos de extensión Unwrap, como se muestra en el siguiente ejemplo.


// Unwrap the inner task.
Task<string> t3 = DoWorkAsync().ContinueWith((s) => DoMoreWorkAsync()).Unwrap();

// Outputs "More work completed."
Console.WriteLine(t.Result);


Los métodos Unwrap se pueden utilizar para transformar Task<Task> o Task<Task<TResult>> (Task(Of Task) o Task(Of Task(Of TResult)) en Visual Basic) en Task o Task<TResult> (Task(Of TResult) en Visual Basic). La nueva tarea representa al completo la tarea anidada interna e incluye el estado de cancelación y todas las excepciones.

En el ejemplo siguiente se muestra cómo usar los métodos de extensión Unwrap.




namespace Unwrap
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    // A program whose only use is to demonstrate Unwrap.
    class Program
    {
        static void Main()
        {
            // An arbitrary threshold value.
            byte threshold = 0x40;

            // data is a Task<byte[]>
            var data = Task<byte[]>.Factory.StartNew(() =>
                {
                    return GetData();
                });

            // We want to return a task so that we can
            // continue from it later in the program.
            // Without Unwrap: stepTwo is a Task<Task<byte[]>>
            // With Unwrap: stepTwo is a Task<byte[]>
            var stepTwo = data.ContinueWith((antecedent) =>
                {                    
                    return Task<byte>.Factory.StartNew( () => Compute(antecedent.Result));                  
                })
                .Unwrap();

            // Without Unwrap: antecedent.Result = Task<byte>
            // and the following method will not compile.
            // With Unwrap: antecedent.Result = byte and
            // we can work directly with the result of the Compute method.
            var lastStep = stepTwo.ContinueWith( (antecedant) =>
                {
                    if (antecedant.Result >= threshold)
                    {
                      return Task.Factory.StartNew( () =>  Console.WriteLine("Program complete. Final = 0x{0:x} threshold = 0x{1:x}", stepTwo.Result, threshold));
                    }
                    else
                    {
                        return DoSomeOtherAsyncronousWork(stepTwo.Result, threshold);
                    }
                });

            lastStep.Wait();
            Console.WriteLine("Press any key");
            Console.ReadKey();
        }

        #region Dummy_Methods
        private static byte[] GetData()
        {
            Random rand = new Random();
            byte[] bytes = new byte[64];
            rand.NextBytes(bytes);
            return bytes;
        }

        static Task DoSomeOtherAsyncronousWork(int i, byte b2) 
        {
            return Task.Factory.StartNew(() =>
                {
                    Thread.SpinWait(500000);
                    Console.WriteLine("Doing more work. Value was <= threshold");
                });
        }
        static byte Compute(byte[] data)
        {

            byte final = 0;
            foreach (byte item in data)
            {
                final ^= item;
                Console.WriteLine("{0:x}", final);
            }
            Console.WriteLine("Done computing");
            return final;
        }
        #endregion
    }
}


Mostrar:
© 2015 Microsoft