我正在尝试通过制作一个简单的小游戏来学习C#线程。我遇到了一些我当然可以使用帮助的问题。
我的愿望是同时输入和输出。线程的输出将显示在屏幕的顶部,而用户的输入可以输入到屏幕的底部。我遇到的问题是,为了刷新屏幕,当我使用Console.Clear()
时,它也会消除用户输入的内容!下面我附上了我正在尝试做的极其简化的版本(为了避免不必要的代码妨碍实际问题)。
请注意:虽然在这个例子中我只更新了屏幕顶部的单个字符,但是我的实际程序在屏幕的顶部和中间会有很多文字,每次打勾都会不断变化(我计划在1.5秒内使用)。
任何想法都会很棒!我仍然是C#编程的新手,并且会为你能给予的任何帮助感到激动:)我唯一关注的是设计。顶部的系统输出,最底部的用户输入前面是“>”。如果我这样做的方式是错误的,那么把它全部抛到窗外并以不同的方式进行操作是没有问题的。
编辑:我的目标是让屏幕顶部的输出文本每1.5秒更新一次(每次运行计数线程),同时允许用户在屏幕底部键入。但是,我正在使用的方法(清除然后将新内容写入屏幕)也消除了用户的输入!它使得每1.5秒无论用户输入什么输入都消失了,这是正确的,因为这正是Console.Clear所做的。所以我正在寻找一种新方法来完成这项任务。
简而言之:如何更新屏幕顶部/中间的文字,同时允许用户继续在屏幕底部输入内容?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication2
{
class Program
{
static int i = 0;
static void Main(string[] args)
{
Thread tickThread = new Thread(new ThreadStart(CountThread));
Thread userThread = new Thread(new ThreadStart(UserInput));
tickThread.Start();
Thread.Sleep(1);
userThread.Start();
Thread.Sleep(20000);
tickThread.Abort();
userThread.Abort();
}
static void UserInput()
{
string input = "";
while (true)
{
input = Console.ReadLine();
}
}
static void CountThread()
{
while (true)
{
Console.Clear();
Console.SetCursorPosition(0, 0);
Console.WriteLine(i);
i++;
Console.SetCursorPosition(0, Console.WindowHeight - 1);
Console.Write("> ");
Thread.Sleep(1500);
}
}
}
}
答案 0 :(得分:1)
您可以在控制台中的每个单元格的循环中设置cursor position,除了为用户输入设计的单元格,并写入空格符号。从本质上讲,这将清除控制台窗口的一部分。 此外,您可以使用相同的方法将输出部分呈现到控制台。
答案 1 :(得分:1)
您可以使用Console.ReadKey
通过字符读取输入字符。如果存储输入,则可以重建整个屏幕,包括在清除控制台之前键入的输入。我建议在一个单独的线程中做所有I / O相关。您可以保留由多个线程更新的控制台的内部表示,然后从一个线程打印它。
这样做!
答案 2 :(得分:0)
您是否考虑使用窗口表单,其中有一个输出面板和一个输入面板?
答案 3 :(得分:0)
这是一种方法,它具有主线程读取控制台输入,以及第二个线程来编写控制台输出:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleReadWriteTest
{
class Program
{
private static ConsoleInfo consoleInfo = new ConsoleInfo();
static void Main(string[] args)
{
Thread consoleWriter = new Thread(new ThreadStart(ConsoleWriter));
consoleWriter.Start();
consoleInfo.outputBuffer.Add("Running.");
consoleInfo.outputBuffer.Add(".. status of foo = good");
consoleInfo.outputBuffer.Add(".. status of bar = bad");
while (true)
{
var key = Console.ReadKey(true);
lock (consoleInfo)
{
if (key.Key == ConsoleKey.Enter)
{
consoleInfo.commandReaty = true;
}
else
{
consoleInfo.sbRead.Append(key.KeyChar.ToString());
}
}
}
}
static void ConsoleWriter()
{
while (true)
{
lock(consoleInfo)
{
Console.Clear();
if (consoleInfo.outputBuffer[0].Length > 20)
{
consoleInfo.outputBuffer[0] = "Running.";
}
else
{
consoleInfo.outputBuffer[0] += ".";
}
foreach (var item in consoleInfo.outputBuffer)
{
Console.WriteLine(item);
}
Console.WriteLine("--------------------------------------------------------------");
if (consoleInfo.commandReaty)
{
consoleInfo.commandReaty = false;
consoleInfo.lastCommand = consoleInfo.sbRead.ToString();
consoleInfo.sbRead.Clear();
consoleInfo.lastResult.Clear();
switch (consoleInfo.lastCommand)
{
case "command1":
consoleInfo.outputBuffer[2] = ".. status of bar = good";
consoleInfo.lastResult.Append("command #1 performed");
break;
case "command2":
consoleInfo.outputBuffer[2] = ".. status of bar = bad";
consoleInfo.lastResult.Append("command #2 performed");
break;
case "?":
consoleInfo.lastResult.AppendLine("Available commands are:");
consoleInfo.lastResult.AppendLine("command1 sets bar to good");
consoleInfo.lastResult.AppendLine("command1 sets bar to bad");
break;
default:
consoleInfo.lastResult.Append("invalid command, type ? to see command list");
break;
}
}
Console.WriteLine(consoleInfo.lastCommand);
Console.WriteLine(consoleInfo.lastResult);
Console.WriteLine();
Console.Write(">");
Console.WriteLine(consoleInfo.sbRead.ToString());
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
}
Thread.Sleep(250);
}
}
private class ConsoleInfo
{
public bool commandReaty { get; set; }
public StringBuilder sbRead { get; set; }
public List<string> outputBuffer { get; set; }
public string lastCommand { get; set; }
public StringBuilder lastResult { get; set; }
public ConsoleInfo()
{
sbRead = new StringBuilder();
outputBuffer = new List<string>();
commandReaty = false;
lastResult = new StringBuilder();
}
}
}
}