darighteous1
darighteous1

Reputation: 89

Simultaneous printing on the console in c#, is it possible?

I'm new to programming and currently I'm trying to learn c#. Here is my question: I have this following piece of code:

static void Main()
    {
        string loading = "LOADING...";
        for (int i = 0; i < 5; i++)
        {
            foreach (var letter in loading)
            {
                Console.Write("{0}", letter);
                Thread.Sleep(250);
            }
            Console.Clear();
            Console.Write("\r");
        }
        for (int k = 0; k <= 100; k++)
        {
            Console.Write("\r{0}%", k);
            Thread.Sleep(150);
        }
    }

I am trying to find a way to execute these two for loops simultaneously. I want to keep re-writing LOADING on the console and under it to print the percentage from 1 to 100. Right now the second for loop runs after the first quits. Is it possible to make them run at the same time? I have been trying to find an answer for a few hours now, but with no luck so far. Thanks!

Upvotes: 0

Views: 1515

Answers (2)

Douglas
Douglas

Reputation: 54897

There is more to this challenge than just running the code in two threads. When multiple threads are attempting to write to the console simultaneously, you are likely to end up with race conditions, where one thread starts writing in the middle of another thread's output.

To protect against this, you need to enforce critical sections, which are regions of your code where only one thread can execute at any time. These would generally consist of:

// Critical section
lock (syncLock)
{
    Console.SetCursorPosition(x, y);
    Console.Write(yourText);
}
Thread.Sleep(yourDelay);

Here is the full code:

// Dummy object to serve as mutual-exclusion lock when synchronizing threads.
private static readonly object syncLock = new object();

public static void Main(string[] args)
{
    // Run two anonymous functions in parallel,
    // then wait for both to complete.
    Parallel.Invoke(

        // Anonymous function for printing "LOADING..."
        () =>
        {
            const string loading = "LOADING...";
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < loading.Length; j++)
                {
                    // Critical section
                    lock (syncLock)
                    {
                        Console.SetCursorPosition(j, 0);
                        Console.Write("{0}", loading[j]);
                    }
                    Thread.Sleep(250);
                }

                // Critical section
                lock (syncLock)
                {
                    Console.SetCursorPosition(0, 0);
                    Console.Write("\r          ");
                }
                Thread.Sleep(250);
            }
        },

        // Anonymous function for printing "x%"
        () =>
        {
            for (int k = 0; k <= 100; k++)
            {
                // Critical section
                lock (syncLock)
                {
                    Console.SetCursorPosition(0, 1);
                    Console.Write("\r{0}%", k);
                }
                Thread.Sleep(150);
            }
        });
    }
}

Upvotes: 0

mariozski
mariozski

Reputation: 1134

As krillgar noted you can use Tasks to run each loop independently. Something like this:

        string loading = "LOADING...";
        var loadingTask = Task.Run(() =>
        {
            for (int i = 0; i < 5; i++)
            {
                foreach (var letter in loading)
                {
                    Console.Write("{0}", letter);
                    Thread.Sleep(250);
                }
                Console.Clear();
                Console.Write("\r");
            }
        });
        var pocTask = Task.Run(() =>
        {
            for (int k = 0; k <= 100; k++)
            {
                Console.Write("\r{0}%", k);
                Thread.Sleep(150);
            }
        });

        Task.WaitAll(loadingTask, pocTask);

Please note however it'll not work as you would expect( first line with LOADING... and second with percentage). That would require some synchronization of displayed messages between those loops and I think that's whole another story and not in the scope of the answer to your question.

Upvotes: 1

Related Questions