2012-03-14 12 views
7

tengo este método que se inicia una tarea y devuelve la última tarea cahined para obtener el resultado:¿Cómo puedo iniciar una instancia de tarea de continuación?

public Task<double> GetTask() 
{ 
    return Task.Factory.StartNew((() => 10)) 
     .ContinueWith(i => 
     { 
      return i.Result + 2; 
     }) 
     .ContinueWith(i => 
     { 
      return (double)i.Result; 
     }); 
} 

me gustaría tener el mismo método de devolución de la misma tarea, pero sin iniciarlo automáticamente con el Task.Factory .StartNew así:

public Task<double> GetTask2() 
{ 
    return new Task<int>((() => 10)) 
     .ContinueWith(i => 
     { 
      return i.Result + 2; 
     }) 
     .ContinueWith(i => 
     { 
      return (double)i.Result; 
     }); 
} 

de todos modos yo no era capaz de encontrar una manera de empezar la tarea devuelta por GetTask2 y obtener el resultado. ¿Cómo puedo comenzar y obtener el resultado?

Respuesta

1

se podría hacer algo como lo siguiente. Como ejemplo, he creado tres TextBox s con fines ilustrativos.

primero seleccione la tarea requerida utilizando un método como

public Task<double> GetTask() 
{ 
    // Return choice of task. 
    return new Task<double>(() => 10.0); 
} 

A continuación, construir la continuación de ese Task seleccionada utilizando un método como (ommitting manejo de errores)

public Task<double> DefineTaskContinuation(Task<double> _task) 
{ 
    _task.ContinueWith(i => 
     { 
      textBox2.Text = (i.Result + 2).ToString(); 
      return i.Result + 2; 
     }, TaskScheduler.FromCurrentSynchronizationContext()) 
    .ContinueWith(i => 
     { 
      textBox3.Text = (i.Result + 2).ToString(); 
     }, TaskScheduler.FromCurrentSynchronizationContext()); 
    return _task; 
} 

El si tiene una forma con textBox1, textBox2 y textBox3, usted podría llenar estos cuadros de texto que utilizan la salida de la countinuation de la siguiente manera

private void button1_Click(object sender, EventArgs e) 
{ 
    Task<double> task = DefineTaskContinuation(GetTask()); 
    task.Start(); 
    textBox1.Text = task.Result.ToString(); 
} 

Salida:

The Results

espero que esto ayude.

Editar: Debido a los comentarios muy correctas por @usr, la respuesta ha sido cambiado. Tenga en cuenta que la TaskScheduler.FromCurrentSynchronizationContext() no es un requisito, pero se utiliza para facilitar mi salida de impresión al hilo de interfaz de usuario. Todo lo mejor.

+1

Esto no funcionará. Necesita comenzar la primera tarea original. No es el último de la cadena. – usr

+0

¿Por qué? Esa no es la pregunta. Simplemente crea una instancia de la tarea desde el método. Entonces comienza. Sencillo. – MoonKnight

+1

Está llamando a comenzar en la tarea de continuación. No puede iniciar la tarea de continuación. Se iniciará automáticamente cuando se complete su antecedente. No puedes obligarlo a comenzar. – usr

2

Algo como esto:

public Task<double> GetTask() 
{ 
    var rootTask = new Task<int>((() => 10)); 
    var continuationTask = rootTask 
     .ContinueWith(i => 
     { 
      return i.Result + 2; 
     }) 
     .ContinueWith(i => 
     { 
      return (double)i.Result; 
     }); 
    rootTask.Start(), 
    return continuationTask; 
} 

Si desea iniciar la tarea sólo más tarde, puede volver tanto de su función.

+0

Esta es una solución factible pero no la respuesta a mi pregunta.Gracias de todos modos. – gigi

+0

¿Qué extrañé con respecto a su pregunta? ¿Por qué es esto factible, pero no una respuesta? – usr

+0

El punto es que no quiero devolver una tupla, sino que la tarea devuelve el resultado final y puedo editarlo, como por ejemplo: task.Root(). Start(). Si lees el título de la pregunta, es explícito. – gigi

0
[TestFixture] 
public class TaskTester 
{ 
    [Test] 
    public void Test() 
    { 
     Tuple<Task<int>, Task<double>> result = GetResult(); 
     result.Item1.Start(); 
     Assert.That(result.Item2.Result, Is.EqualTo(12)); 
    } 

    private static Tuple<Task<int>, Task<double>> GetResult() 
    { 
     var task1 = new Task<int>(() => 10); 
     Task<int> task2 = task1.ContinueWith(i => i.Result + 2); 
     Task<double> task3 = task2.ContinueWith(i => (double)i.Result); 
     return new Tuple<Task<int>, Task<double>>(task1, task3); 
    } 
} 
2

Se puede crear otra Task, que comienza el padre Task, a continuación, establece la continuación y devuelve el resultado de la continuación. Aunque tiene la desventaja de que puede bloquear un hilo mientras espera que el que en realidad calcule las continuidades se complete.

public static Task<double> GetTask() 
{ 
    return new Task<double>(
     () => Task.Factory.StartNew(() => 10) 
        .ContinueWith(
         i => 
         { 
          return i.Result + 2; 
         }) 
        .ContinueWith(
         i => 
         { 
          return (double)i.Result; 
         }).Result); 
} 
Cuestiones relacionadas