如何启动延续任务实例?

时间:2012-03-14 16:04:12

标签: c# .net task-parallel-library

我有这个方法,启动一个任务并返回最后一个cahined Task来获得结果:

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返回的任务的方法并获得结果。我怎样才能开始并获得结果?

4 个答案:

答案 0 :(得分: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;
}

如果您想稍后启动任务,可以从函数返回两者。

答案 1 :(得分: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);
}

答案 2 :(得分:1)

您可以执行以下操作。作为一个例子,我创建了三个TextBox用于说明目的。

首先使用

之类的方法选择所需的任务
public Task<double> GetTask()
{
    // Return choice of task.
    return new Task<double>(() => 10.0);
}

然后使用类似(省略错误处理)的方法为所选Task构建延续

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

如果您的表单包含textBox1textBox2textBox3,则可以使用计数输出填写这些文本框,如下所示

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线程。一切顺利。

答案 3 :(得分: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);
    }
}