2012-03-14 81 views
7

我有开始一个任务并返回最后cahined任务得到结果这个方法:如何启动延续任务实例?

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

我想有同样的方法返回相同的任务,但不与Task.Factory自动启动它.StartNew这样的:

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

反正我没能找到一种方法来启动由GetTask2返回的任务,并得到结果。我如何启动并获得结果?

回答

1

你可以做如下的事情。作为一个例子,我创建了三个TextBox用于说明目的。

首先使用像

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

的方法然后建立使用类似(ommitting错误处理)

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; 
} 

的,如果你有一个形式的方法是选择Task继续选择您所需的任务使用textBox1,textBox2textBox3,您可以使用如下计数的输出来填充这些文本框

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

输出:

The Results

我希望这有助于。

编辑:由于@usr非常正确的评论,答案已经改变。请注意,TaskScheduler.FromCurrentSynchronizationContext()不是必需条件,但用于促进我的打印输出到UI线程。祝一切顺利。

+1

这是行不通的。你需要开始原始的第一项任务。不是链的最后一个。 – usr 2012-03-14 16:22:08

+0

为什么?这不是问题。只是从该方法实例化任务。然后启动它。简单。 – MoonKnight 2012-03-14 16:24:58

+1

您正在调用开始继续任务。您无法启动延续任务。它的前奏完成时它会自动启动。你不能强迫它开始。 – usr 2012-03-14 17:09:34

2

事情是这样的:

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; 
} 

如果你想后来才启动任务,你可以从你的函数返回两者。

+0

这是一个可行的解决方案,但不是我的问题的答案。不管怎样,谢谢你。 – gigi 2012-03-14 17:43:38

+0

关于你的问题,我错过了什么?为什么这是可行的,但不是答案? – usr 2012-03-14 17:45:17

+0

的一点是,我dont'want返回一条记录,但在返回最终结果的任务,并能够SART它,就像例如:task.Root()启动()。如果您阅读问题标题,则是明确的。 – gigi 2012-03-15 08:51:40

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

你可以创建另一个Task,启动父Task,然后建立了延续,并返回延续的结果。虽然它有一个缺点,那就是在等待实际计算延续完成的线程时可能会阻塞一个线程。

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); 
}