简体   繁体   中英

Ordering of tasks in TPL

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM