【问题标题】:How to read/write on console at the same time using threads如何使用线程同时在控制台上读/写
【发布时间】:2023-12-19 07:28:02
【问题描述】:

我想实现一个运行模拟的 C# 控制台应用程序。另外,我想为用户提供加速/减速模拟速度的机会,在控制台上按“+”或“-”。

有没有办法一边写一边读控制台?我相信我可以为此使用多线程,但我不知道该怎么做(我还是 C# 的新手)。

非常感谢!

【问题讨论】:

  • 你想模拟什么,更重要的是你打算用什么数据结构来模拟问题?
  • 我想模拟一个游戏。代表角色的字母在“体育场”内随机移动,当它们离得太近时,它们会互相争斗。基本上,我会显示体育场、移动字母并显示所选角色的信息以及模拟运行了多少秒。

标签: c# multithreading console simulation


【解决方案1】:

是的,有一种“同时”读/写的方法。有几种方法可以做到:

使用另一个线程:

首先,您启动一​​个负责写入控制台的线程。

Thread t = new Thread(()=>{RunSimulation();});
t.IsBackground = true;
t.Start();

模拟方法看起来类似于:

public void RunSimulation()
{
    while(running)
    {
        // Puts the thread to sleep depending on the run speed
        Thread.Sleep(delayTime);
        Console.WriteLine("Write your output to console!");
    }
}

其次,您可以不断地让主线程轮询用户输入以进行调整。

string input = string.Empty;

while(input.Equals("x", StringComparison.CurrentCultureIgnoreCase)
{
    input = Console.ReadKey();
    switch(input)
    {
    case "+":
        // speeds up the simulation by decreasing the delayTime
        IncreaseSpeed();
        break;
    case "-":
        // slows down the simulation by decreasing the delayTime
        DecreaseSpeed();
        break;
    default:
        break;
    }
}

使用计时器:

另一种方法是使用 [Timer][1] 并调整计时器上的回调频率,而不是调整线程上的睡眠时间:

// Create the timer
System.Timers.Timer aTimer = new System.Timers.Timer(10000);

// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnPrintSimulationResult);

// Change the Interval to change the speed of the simulation
aTimer.Interval = 2000; // <-- Allows you to control the speed of the simulation
aTimer.Enabled = true;

当然,您必须处理线程安全,但这应该给您一个不错的起点。一旦您尝试了其中一种方法并且遇到了特定问题,您就可以回来,我相信人们会很乐意解决您遇到的任何特定问题。请注意,在控制台中执行此操作并不是一个非常优雅的解决方案,但它会起作用。如果您想要更优雅的东西,那么只需制作一个具有文本区域的 GUI 应用程序,将控制台输出重定向到文本区域并添加 2 个按钮 (+/-) 来调整速度。 [1]:http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx

【讨论】:

  • 输入永远不能等于“退出”,因为它一次被分配一个按键......
  • @Reed,是的...有点复制和粘贴代码的 sn-ps。修复了这个问题,但更应该从这里拿走一般的想法。
  • 我被重定向到这个问题,因为我有一个非常相似的问题。我注意到这个答案是从 2011 年开始的,鉴于过去 10 年对 .NET 的更改,您会为线程采用不同的方法吗?
  • @JansthcirlU 自 2013 年以来我几乎没有写过任何代码。我怀疑该语言自 2011 年以来已经成熟了很多。不幸的是,我不知道它是如何发展的。 :) 事实上,现在我看着它......我怀疑RunSimulation 循环不能正常工作,因为delayTime 不是原子的。 delayTime 更好的名字是 simulationSpeed :)
【解决方案2】:

您可以在致电Console.ReadKey() 之前查看Console.KeyAvailable。这将让您检查控制台以查看是否有输入等待(即:用户按下 + 或 -)没有阻塞。如果您只是在没有可用输入时不尝试读取,您的主线程将永远不会阻塞等待用户。

使用这种机制,您实际上可以在单线程应用程序中执行此操作。

【讨论】:

    最近更新 更多