2012-03-14 9 views
7

私は、タスクを起動し、結果を得るために、最後のcahinedタスクを返します。この方法があります:私は、同じタスクを返す同じメソッドを持ちたいけどTask.Factoryと、自動的にそれを起動することなくなり継続タスクインスタンスを開始するにはどうすればよいですか?

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

を.StartNewこのように:

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

とにかく私はGetTask2によって返されたタスクを開始し、結果を得る方法を見つけることができませんでした。どのように私はそれを開始し、結果を得ることができますか?

答えて

1

次のようなことができます。例として、説明のために3つのTextBoxを作成しました。

まず(エラー処理をommitting)などのメソッドを使用して、その選択したTaskための継続を構築

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

のような方法を使用して、必要なタスクを選択し

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

ザ・フォームを持っている場合textBox1,textBox2およびtextBox3と入力すると、次のように数の出力を使用してこれらのテキストボックスを埋め込むことができます

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

+0

なぜですか?それは問題ではありません。メソッドからタスクをインスタンス化するだけです。その後、それを開始します。シンプル。 – MoonKnight

+1

継続タスクで開始を呼び出しています。継続タスクを開始することはできません。 antecendentが完了すると自動的に起動します。あなたはそれを強制的に開始することはできません。 – usr

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

+0

あなたの質問には何が欠けていましたか?なぜこれは実現可能ですが、答えはありませんか? – usr

+0

要点は、タプルを返すのではなく、最終結果を返すタスクであり、たとえば、task.Root()。Start()のようにそれを捨てることができないということです。あなたが質問のタイトルを読んだら、それは明白です。 – 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

あなたは、その後、親Taskを開始し、継続を設定し、継続の結果を返す別のTaskを作成することができます。実際にその継続を完了するのを待っている間に1つのスレッドをブロックすることがあるという欠点があります。

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); 
} 
関連する問題