If I have the following code

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

I want main to start first, then 2 dependencies can start after that which in parallel which are first and second. I want to then return a future with the value for the caller to add a continuation on. However i want to ensure second and third have run first. Is the code below the best way to achieve this? Seems kinda clunky

有帮助吗?

解决方案

I'm not too familiar with TPL, but isn't this what ContinueWhenAll is for?

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

I don't know how to get main's result from the completed second and third (contained in twotasks), but maybe you can modify them to pass through the result.

Edit: Or, as Alex points out, use

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

and read the result from threetasks[0].

其他提示

This would suffice:

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;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top