Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why nothing is printed on the console?

Tags:

c#

async-await

I create 2 methods that print x and y 100 times. I want them to run concurrent and I expect the output to be xxxxyxyxyyyxyyxyx... sthg like that. It doesn't print anything. Am I missing some logic here?

using System;
using System.Threading.Tasks;

namespace ConsoleApplication32
{
    internal class Program
    {
        public static async Task<int> Print1()
        {
            await Task.Run(() =>
            {
                for (int i = 0; i < 100; i++)
                {
                    Console.Write("x");
                }
            });

            return 1;
        }

        public static async Task<int> Print2()
        {
            await Task.Run(() =>
            {
                for (int i = 0; i < 100; i++)
                {
                    Console.Write("y");
                }
            });

            return 1;
        }

        public static void Run()
        {
            Task<int> i = Print1();
            Task<int> k = Print2();
        }

        private static void Main(string[] args)
        {
            Run();
        }
    }
}
like image 326
Lyrk Avatar asked Aug 11 '17 12:08

Lyrk


People also ask

What will be printed on the console?

Answer: Void main will be printed on the console.

How do I print text from console?

To print a String to console output, you can use System. out. print() or System.


1 Answers

Explanation

There are a couple things we need to tweak to get the desired output: xxxxyxyxyyyxyyxyx.

  1. The Run method is not waiting for Task i and Task k to finish

    • This means that the console application will close before the two Tasks complete
    • As Andrei Matracaru mentions in his answer, if you add Console.ReadLine(), it will prevent the console application from closing before the strings have been printed to the screen.
    • A more elegant solution is to use Task.WhenAll. Task.WhenAll will allow the code yield to its calling thread (in this case, the Main Thread) which doesn't freeze the UI of the application, and allows the application to continue to print to the screen until the Tasks have completed. This may seem trivial for a simple console app, but it is crucial to never lock up the Main Thread when building any user-interactive application like mobile or web applications; locking up the Main Thread is what causing apps to "freeze".
    • Camilo Terevinto's answer above recommends Task.WaitAll. This is also bad practice because it will also freeze the application; Task.WaitAll is not awaitable and cannot not yield to the calling thread.
  2. Print1() and Print2() never yield to the Main Thread

    • These methods are executing on a background thread, but they don't include an await inside of the for loop
    • An await is necessary inside of the for loop to allow CPU to continue executing the Main Thread, because Console.Write() can only print to the screen on the Main Thread.

Code

using System;
using System.Threading.Tasks;

namespace ConsoleApplication32
{
    internal class Program
    {
        public static async Task<int> Print1()
        {
            for (int i = 0; i < 100; i++)
            {
                Console.Write("x");
                await Task.Delay(10);
            }

            return 1;
        }

        public static async Task<int> Print2()
        {
            for (int i = 0; i < 100; i++)
            {
                Console.Write("y");
                await Task.Delay(10);
            }

            return 1;
        }

        public static async Task Run()
        {
            var i = Print1();
            var k = Print2();

            await Task.WhenAll(i, k);
        }

        private static void Main(string[] args)
        {
            Task.Run(async () => await Run()).GetAwaiter().GetResult();
        }
    }
}

Output

xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxxyxyxyxy Press any key to continue...

C# 7.1 Alternative

C# 7.1 introduces the ability to have an async Main method. This means that we can tweak the Main method as follows:

    ...

    private static async Task Main(string[] args)
    {
        await Run();
    }
    ...
like image 163
Brandon Minnick Avatar answered Nov 04 '22 20:11

Brandon Minnick