最近在学习C#控制台多线程时遇到了一个问题
我写了一个TCP客户端用于接受服务器的消息,当然TCP客户端的接收都是多线程,我需要将客户端收到的消息都在那个线程中使用Console.WriteLine输出。
但是我的主线程内写了一个循环 用于接收用户的命令 (也就是写了一个while循环一直Console.ReadLine)。
当我正在输入内容时如果TCP客户端突然收到消息,就会发生下面的情况
我写了制作了一个模拟程序,来模拟多线程情况其他程序换行输出导致用户尝试输入的命令也跟着换行的问题
using System.Diagnostics;
Task.Run(async () =>
{
while (true)
{
Console.WriteLine("模拟多线程情况下其他线程输入的情况");
await Task.Delay(300);
}
});
while (true)
{
string? cmd = Console.ReadLine();
if (null != cmd)
{
Console.WriteLine($"你输入了:{cmd}");
Process.GetCurrentProcess().Kill();
}
}
我对C#的Console不是很了解,只知道输入、输出、清空、设置颜色这些基本的方法。
Console有一个SetCursorPosition方法
记录用户每一次在控制台内的输入,使用一个变量存起来
WriteLine之后使用SetCursorPosition设置输出位置到这一次WriteLine之后 (也就是再换一次行
换行之后把之前用户的输入再打印出来
不过我觉得这个想法不行,有这些问题
打印出来的内容还是会导致错位(也就是无法清空残留消息)
其他线程WriteLine时保留用户对控制台的输入
可以用 Console.ReadKey()读内容,判断在读取信息时将task中的输出内容压入数组中而不是直接输出,输入完毕(按下enter后)则输出数组中的的内容,简单示例如下
using System;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Collections.Generic;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
var lst = new List<string>();
var inputing = false;
var count = 1;
Task.Run(async () =>
{
while (true)
{
if (inputing) lst.Add("模拟多线程情况下其他线程输入的情况"+ count);
else Console.WriteLine("模拟多线程情况下其他线程输入的情况" + count);
count++;
await Task.Delay(300);
}
});
while (true)
{
var cmd = "";
while (true)
{
var key = Console.ReadKey();
inputing = true;
if (key.Key == ConsoleKey.Enter)
{
inputing = false;
break;
}
else cmd += key.KeyChar;
}
Console.WriteLine(cmd);
if (cmd == "")
{
Console.WriteLine($"你输入了:{cmd}");
Process.GetCurrentProcess().Kill(); ;
}
if (lst.Count > 0)
{
Console.WriteLine(string.Join("\n", lst));
lst.Clear();
}
}
}
}
}
你的意思是你写了一个程序,用于接收消息。
但是你的应用程序还能在接受消息的同时能够输入消息。
学一下winform做界面程序吧。
或者把你的接收的消息写到文件里去。
否则你没有办法在一个控制台,做 入和出。