简体   繁体   中英

Task WaitAll return List object in c#

I have created this code to understand about "Task.WaitAll ()" in c#.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;

namespace taskApp
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Task> p = new List<Task>();

            Task task1 = MultipleTasks();
            Task task2 = Hello(40);
            Task task3 = Bye(10);
            Task.WaitAll(task1, task2, task3);

            var a = 1;
            a = a + 1;
        }

        private static async Task Hello(int delay)
        {
            await Task.Delay(delay);
            Console.WriteLine($"+++ End Process: {nameof(Hello)}, delay: {delay} +++ ");
        }

        private static async Task Bye(int delay)
        {
            await Task.Delay(delay);
            Console.WriteLine($"+++ End Process: {nameof(Bye)}, delay: {delay} +++ ");
        }
        private static async Task<List<MyClass>> MultipleTasks()
        {
            List<Task<MyClass>> psTask = new List<Task<MyClass>>();
            List<MyClass> ps = new List<MyClass>();

            for (int i = 0; i < 3; i++)
                psTask.Add(getTest(i));

            Task.WaitAll(psTask.ToArray());

            ps = psTask.Select(c => c.Result).ToList();

            return ps;
        }

        private static async Task<MyClass> getTest(int i)
        {
            MyClass p = new MyClass();
            int delay = 0;
            switch (i)
            {
                case 0:
                    delay = 4000;
                    p.delayUsed = delay;
                    p.message = "cero";
                    break;
                case 1:
                    delay = 1000;
                    p.delayUsed = delay;
                    p.message = "uno";
                    break;
                case 2:
                    delay = 7000;
                    p.delayUsed = delay;
                    p.message = "dos";
                    break;
                case 3:
                    delay = 2000;
                    p.delayUsed = delay;
                    p.message = "tres";
                    break;
                default:
                    p.message = "default";
                    break;
            }

            await Task.Delay(p.delayUsed);
            Console.WriteLine($"+++ End Process: {nameof(getTest)} {i}, delay: {delay} +++ ");
            return p;
        }
    }

    public class MyClass
    {
        public int delayUsed { get; set; }
        public string message { get; set; }
    }
}

This is the order that the console application runs

+++ End Process: getTest 1, delay: 1000 +++
+++ End Process: getTest 0, delay: 4000 +++
+++ End Process: getTest 2, delay: 7000 +++
+++ End Process: Bye, delay: 10 +++
+++ End Process: Hello, delay: 40 +++

The correct order that my application should run is as follows:

+++ End Process: Bye, delay: 10 +++
+++ End Process: Hello, delay: 40 +++
+++ End Process: getTest 1, delay: 1000 +++
+++ End Process: getTest 0, delay: 4000 +++
+++ End Process: getTest 2, delay: 7000 +++

Following the logic of the delay time of each method, the correct execution order is deduced

enter image description here

This is the help that "visual studio 2019" gives me.

And effectively the "MultipleTasks ()" method is executed synchronously.

Can someone tell me how I can make the console application behave correctly?.

The problem is that you're awaiting during the creation of the tasks and not just their execution.

First, change your MultipleTasks() method to read like this (returning List<Task> ):

    private static List<Task> MultipleTasks()
    {
        List<Task> psTask = new List<Task>();

        for (int i = 0; i < 3; i++)
            psTask.Add(getTest(i));

        return psTask;
    }

Then change the getTest() method to return Task , like this:

    private static async Task getTest(int i)
    {
        // snip

        await Task.Delay(p.delayUsed);
        Console.WriteLine($"+++ End Process: {nameof(getTest)} {i}, delay: {delay} +++ ");
    }

Finally, create and execute your tasks like this:

    static void Main(string[] args)
    {
        var tasks = MultipleTasks();

        tasks.Add(Hello(40));
        tasks.Add(Bye(10));
        
        Task.WaitAll(tasks.ToArray());

        Console.ReadKey();
    }

The output should then be what you're looking for:

在此处输入图像描述

This is what i wanted to achieve, thank you very much for your help.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;

namespace taskApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++ ");
            Console.WriteLine($"+++ Asynchronous code +++ ");
            Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++ ");
            List<Task<MyClass>> tasks = MultipleTasks();
            Task<MyClass> task2 = Hello(400);
            Task<MyClass> task3 = Bye(10);

            tasks.Add(task3);
            tasks.Add(task2);

            Task.WaitAll(tasks.ToArray());

            //from here it runs synchronously

            MyClass a = task2.Result;
            MyClass b = task3.Result;

            List<MyClass> c = tasks.Select(c => c.Result).ToList();
            Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++ ");
            Console.WriteLine($"+++ Synchronous code ++++ ");
            Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++ ");
            Console.WriteLine($"+++ Run {nameof(task2)}: message {a.message}, delay {a.delayUsed}+++ ");
            Console.WriteLine($"+++ Run {nameof(task3)}: message {b.message}, delay {b.delayUsed}+++ ");
            Console.WriteLine();

            foreach (var item in c)
            {
                Console.WriteLine($"+++ Run {nameof(tasks)}: message: {item.message}, delay {item.delayUsed} +++ ");
            }
            Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++ ");
        }

        private static async Task<MyClass> Hello(int delay)
        {
            MyClass p = new MyClass();
            p.delayUsed = delay;
            p.message = $"Procedure {nameof(Hello)}";

            await Task.Delay(delay);
            Console.WriteLine($"+++ End Process: {nameof(Hello)}, delay: {delay} +++ ");
            return p;
        }

        private static async Task<MyClass> Bye(int delay)
        {
            MyClass p = new MyClass();
            p.delayUsed = delay;
            p.message = $"Procedure {nameof(Bye)}";
            await Task.Delay(delay);
            Console.WriteLine($"+++ End Process: {nameof(Bye)}, delay: {delay} +++ ");
            return p;
        }
        private static List<Task<MyClass>> MultipleTasks()
        {
            List<Task<MyClass>> psTask = new List<Task<MyClass>>();

            for (int i = 0; i < 3; i++)
                psTask.Add(getTest(i));

            return psTask;
        }

        private static async Task<MyClass> getTest(int i)
        {
            MyClass p = new MyClass();
            int delay = 0;
            switch (i)
            {
                case 0:
                    delay = 4000;
                    p.delayUsed = delay;
                    break;
                case 1:
                    delay = 1000;
                    p.delayUsed = delay;
                    break;
                case 2:
                    delay = 7000;
                    p.delayUsed = delay;
                    break;
                case 3:
                    delay = 2000;
                    p.delayUsed = delay;
                    break;
                default:
                    delay = 0;
                    break;
            }

            p.message = $"Procedure {nameof(getTest)}({i})";
            await Task.Delay(p.delayUsed);
            Console.WriteLine($"+++ End Process: {nameof(getTest)}({i}), delay: {delay} +++ ");
            return p;
        }
    }

    public class MyClass
    {
        public int delayUsed { get; set; }
        public string message { get; set; }
    }
}

Result

++++++++++++++++++++++++++++++++++++++++
+++ Asynchronous code +++
++++++++++++++++++++++++++++++++++++++++
+++ End Process: Bye, delay: 10 +++
+++ End Process: Hello, delay: 400 +++
+++ End Process: getTest(1), delay: 1000 +++
+++ End Process: getTest(0), delay: 4000 +++
+++ End Process: getTest(2), delay: 7000 +++
++++++++++++++++++++++++++++++++++++++++
+++ Synchronous code ++++
++++++++++++++++++++++++++++++++++++++++
+++ Run task2: message Procedure Hello, delay 400+++
+++ Run task3: message Procedure Bye, delay 10+++

+++ Run tasks: message: Procedure getTest(0), delay 4000 +++
+++ Run tasks: message: Procedure getTest(1), delay 1000 +++
+++ Run tasks: message: Procedure getTest(2), delay 7000 +++
+++ Run tasks: message: Procedure Bye, delay 10 +++
+++ Run tasks: message: Procedure Hello, delay 400 +++
++++++++++++++++++++++++++++++++++++++++

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