简体   繁体   中英

Task.Run vs Task.WhenAll vs Parallel.Invoke vs others: Run tasks in parallel and Get result in C#

Is the code in Option 1 below the best way to achieve in running tasks in parallel?

Option 1

var w = Task.Run(async () => await Work1());
var w2 = Task.Run(async () => await Work2());
Console.WriteLine("end: " + DateTime.Now.ToString("hh:mm:ss.fff"));
await w;
await w2;
Console.WriteLine("last: " + DateTime.Now.ToString("hh:mm:ss.fff") + " " + w.Result + " " + w2.Result);
Console.WriteLine("end");

Result:

end: 06:07:13.054
Work2 s 06:07:13.057
Work1 s 06:07:13.057
Work1 e 06:07:16.072
Work2 e 06:07:17.066
last: 06:07:17.066 1 2

option 2: It swithes to other work upon await, ie. not really in parallel.

            var tasks = new List<Task<int>>();
            tasks.Add(Work1());
            tasks.Add(Work2());
            Console.WriteLine("end: " + DateTime.Now.ToString("hh:mm:ss.fff"));
            await Task.WhenAll(tasks);
            Console.WriteLine("end2: " + DateTime.Now.ToString("hh:mm:ss.fff"));
            Console.WriteLine("last: " + DateTime.Now.ToString("hh:mm:ss.fff") + " " + tasks[0].Result + " " + tasks[1].Result);

Result:

Work1 s 06:11:42.565
Work2 s 06:11:44.571
Work1 e 06:11:45.579
end: 06:11:47.572
Work2 e 06:11:48.574
end2: 06:11:48.575
last: 06:11:48.579 1 2

Tasks

  private static async Task<int> Work1()
        {
            Console.WriteLine("Work1 s " + DateTime.Now.ToString("hh:mm:ss.fff"));
            Thread.Sleep(2000);
            await Task.Delay(1000);
            Console.WriteLine("Work1 e " + DateTime.Now.ToString("hh:mm:ss.fff"));
            return 1;
        }

        private static async Task<int> Work2()
        {
            Console.WriteLine("Work2 s " + DateTime.Now.ToString("hh:mm:ss.fff"));
            Thread.Sleep(3000);
            await Task.Delay(1000);
            Console.WriteLine("Work2 e " + DateTime.Now.ToString("hh:mm:ss.fff"));
            return 2;
        }

Parallel.Invoke() doesn't return result.

Parallel.Invoke() accepts params Action[] that mean you need to pass an list, if to be more accurate - array of actions, action to it. In simpler words you need to pass a method to execute. Simply invoking Parallel.Invoke() wont do a thing.

Here is an example from Parallel tutorial

using System;
using System.Threading.Tasks;

class Program
{
    static void Test()
    {
        Console.WriteLine("Test");
    }

    static void Test2()
    {
        Console.WriteLine("Test2");
    }

    static void Test3()
    {
        Console.WriteLine("Test3");
    }

    static void Main()
    {
        Parallel.Invoke(Test, Test2, Test3);
        Console.WriteLine("[INTERMEDIATE]");
        Parallel.Invoke(Test, Test2, Test3);
    }
}

After reading more carefull your question, more thoughs came to my head. What if you tried to use Parallel.ForEach() ?

It probably could look something like this:

Parallel.ForEach(tasks, task =>{
var result = task.Invoke();
//You can do whatever you want with result
});

Assuming that tasks is List<Task<int>> , if to be more precise - IEnumerable<Task<int>> , of tasks that you need to perform.

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