【问题标题】:Simultaneous printing on the console in c#, is it possible?在c#中的控制台上同时打印,可以吗?
【发布时间】:2015-02-19 21:10:17
【问题描述】:

我是编程新手,目前我正在尝试学习 c#。这是我的问题: 我有以下这段代码:

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

我正在尝试找到一种方法来同时执行这两个 for 循环。我想继续在控制台上重写 LOADING 并在其下打印从 1 到 100 的百分比。现在第二个 for 循环在第一个退出后运行。是否可以让它们同时运行?我一直试图找到几个小时的答案,但到目前为止还没有运气。 谢谢!

【问题讨论】:

  • 为了做到这一点,您需要了解线程或任务。两者都不是初学者主题。这是可以做到的,但你现在不必担心,除非你想一头扎进深渊。
  • ... 才发现池是空的....
  • 感谢 krillgar。看来我需要更多的学习!

标签: c# loops console-application simultaneous


【解决方案1】:

正如 krillgar 所说,您可以使用任务来独立运行每个循环。像这样的:

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

请注意,但它不会像您期望的那样工作(第一行是 LOADING...,第二行是百分比)。这将需要在这些循环之间对显示的消息进行一些同步,我认为这完全是另一回事,不在您问题的答案范围内。

【讨论】:

  • 非常感谢!我将阅读有关任务的内容。在这一点上,也许它对我来说太先进了,但至少要了解总体思路。
【解决方案2】:

这个挑战不仅仅是在两个线程中运行代码。当多个线程同时尝试写入控制台时,您很可能会遇到竞争条件,即一个线程在另一个线程的输出中间开始写入。

为了防止这种情况发生,您需要强制执行关键部分,即代码中在任何时候只有一个线程可以执行的区域。这些通常包括:

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

这里是完整的代码:

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

【讨论】:

  • 我可以通过将光标设置为每个打印循环的不同坐标来避免这种干扰吗?
猜你喜欢
  • 2013-06-15
  • 1970-01-01
  • 2016-03-31
  • 2019-11-22
  • 2012-09-27
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
  • 2016-09-07
相关资源
最近更新 更多