2012-03-14 74 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); 
}