【问题标题】:Ordering of tasks in TPLTPL 中的任务排序
【发布时间】:2013-01-17 08:18:00
【问题描述】:

如果我有以下代码

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    class Program
    {
        static Task<int> GetSuperLargeNumber()
        {
            var main = Task.Factory.StartNew(() =>
                                                 {
                                                     Thread.Sleep(1000);
                                                     return 100;
                                                 });
            var second = main.ContinueWith(x => Console.WriteLine("Second: " + x.Result), TaskContinuationOptions.AttachedToParent);
            var third = main.ContinueWith(x => Console.WriteLine("Third: " + x.Result), TaskContinuationOptions.AttachedToParent);

            return main.ContinueWith(x  =>
                                             {
                                                 Task.WaitAll(second, third);
                                                 return x.Result;
                                             });
        }

        static void Main(string[] args)
        {
            GetSuperLargeNumber().ContinueWith(x => Console.WriteLine("Complete"));

            Console.ReadKey();
        }
    }
}

我希望 main 首先启动,然后 2 个依赖项可以在并行启动之后启动,它们是第一个和第二个。然后我想返回一个带有值的未来,供调用者添加一个延续。但是我想确保第二个和第三个先运行。下面的代码是实现这一目标的最佳方法吗?感觉有点笨重

【问题讨论】:

  • 你使用AttachedToParent的方式没有任何意义。 “父”是当前正在执行的Task,但您的代码中没有。

标签: c# asynchronous concurrency task-parallel-library concurrent-programming


【解决方案1】:

我对 TPL 不太熟悉,但这不就是 ContinueWhenAll 的用途吗?

static Task<int> GetSuperLargeNumber()
{
    var main = Task.Factory.StartNew(() =>
                                         {
                                             Thread.Sleep(1000);
                                             return 100;
                                         });
    var second = main.ContinueWith(
        x => Console.WriteLine("Second: " + x.Result),
        TaskContinuationOptions.AttachedToParent);
    var third = main.ContinueWith(
        x => Console.WriteLine("Third: " + x.Result),
        TaskContinuationOptions.AttachedToParent);

    return Task.Factory.ContinueWhenAll(
        new[] { second, third },
        (twotasks) => /* not sure how to get the original result here */);
    }

我不知道如何从完成的secondthird(包含在twotasks)中得到main 的结果,但也许你可以修改它们以传递结果。

编辑:或者,正如Alex 指出的那样,使用

Task.Factory.ContinueWhenAll(new[] { main, second, third }, (threetasks) => ...

并从threetasks[0]读取结果。

【讨论】:

  • 你可以ContinueWhenAll(new [] { main, second, third}),它可以让你提取main的结果。
  • @Alex Huh,这行得通,谢谢 :) 这仍然有点奇怪,因为你知道如果secondthird 是,则必须完成main完成了,但它比原来的解决方法更简洁。
【解决方案2】:

这就足够了:

static Task<int> GetSuperLargeNumber()
{
    var main = Task.Factory.StartNew<int>(() =>
    {
        Thread.Sleep(1000);
        return 100;
    });
    var second = main.ContinueWith(x => Console.WriteLine("Second: " + x.Result), TaskContinuationOptions.AttachedToParent);
    var third = main.ContinueWith(x => Console.WriteLine("Third: " + x.Result), TaskContinuationOptions.AttachedToParent);

    Task.WaitAll(second, third);

    return main;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多