qq_43045565 2022-08-27 01:02 采纳率: 75%
浏览 47
已结题

控制台应用程序多线程情况下ReadLine时别的线程输出换行导致窜行的问题该如何解决

问题遇到的现象和发生背景

最近在学习C#控制台多线程时遇到了一个问题
我写了一个TCP客户端用于接受服务器的消息,当然TCP客户端的接收都是多线程,我需要将客户端收到的消息都在那个线程中使用Console.WriteLine输出。
但是我的主线程内写了一个循环 用于接收用户的命令 (也就是写了一个while循环一直Console.ReadLine)。
当我正在输入内容时如果TCP客户端突然收到消息,就会发生下面的情况

img

问题相关代码,请勿粘贴截图

我写了制作了一个模拟程序,来模拟多线程情况其他程序换行输出导致用户尝试输入的命令也跟着换行的问题

img

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之后 (也就是再换一次行
换行之后把之前用户的输入再打印出来

不过我觉得这个想法不行,有这些问题
打印出来的内容还是会导致错位(也就是无法清空残留消息)

img

我想要达到的结果

其他线程WriteLine时保留用户对控制台的输入

img

  • 写回答

3条回答 默认 最新

  • CSDN专家-showbo 2022-08-27 13:14
    关注

    可以用 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();
                    }
                }
            }
        }
    }
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 9月4日
  • 已采纳回答 8月27日
  • 修改了问题 8月27日
  • 创建了问题 8月27日

悬赏问题

  • ¥15 linux驱动,linux应用,多线程
  • ¥20 我要一个分身加定位两个功能的安卓app
  • ¥15 基于FOC驱动器,如何实现卡丁车下坡无阻力的遛坡的效果
  • ¥15 IAR程序莫名变量多重定义
  • ¥15 (标签-UDP|关键词-client)
  • ¥15 关于库卡officelite无法与虚拟机通讯的问题
  • ¥15 目标检测项目无法读取视频
  • ¥15 GEO datasets中基因芯片数据仅仅提供了normalized signal如何进行差异分析
  • ¥100 求采集电商背景音乐的方法
  • ¥15 数学建模竞赛求指导帮助