Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#控制台:边读边写并保留结构_C#_Multithreading_Console_Client Server - Fatal编程技术网

C#控制台:边读边写并保留结构

C#控制台:边读边写并保留结构,c#,multithreading,console,client-server,C#,Multithreading,Console,Client Server,我正在编写一个通过TCP连接到服务器的C#console应用程序,它使用一个单独的线程来侦听来自服务器的传入消息,我希望它将消息写入控制台,同时从控制台读取消息。我能做到,但我有个问题 当我键入并收到一条消息时,控制台显示: 来自服务器的消息 来自服务器的消息 我的msmsg来自服务器 g到服务器 我希望它将我的消息与服务器分开,如下所示: 来自服务器的消息 来自服务器的消息 来自服务器的消息 我的邮件发送到服务器 如果我收到一封邮件,我仍然希望保留键入的邮件,但我不希望它与收到的邮件混淆,我希

我正在编写一个通过TCP连接到服务器的C#console应用程序,它使用一个单独的线程来侦听来自服务器的传入消息,我希望它将消息写入控制台,同时从控制台读取消息。我能做到,但我有个问题

当我键入并收到一条消息时,控制台显示:

来自服务器的消息
来自服务器的消息
我的msmsg来自服务器
g到服务器

我希望它将我的消息与服务器分开,如下所示:

来自服务器的消息
来自服务器的消息
来自服务器的消息
我的邮件发送到服务器

如果我收到一封邮件,我仍然希望保留键入的邮件,但我不希望它与收到的邮件混淆,我希望它在最后一行保持完整

我可以这样做吗?怎么做


当来自服务器的消息传入时,我可以将消息移到控制台的末尾吗?

您不能通过C#中的BCL直接执行此操作。不过,有两个主要的选择

1) 将其转换为GUI应用程序,并具有单独的输入/输出区域。这是用户POV中最“清晰”的选项,但需要GUI应用程序而不是控制台应用程序


2) p/Invoke直接调用到。这使您可以逐点完全控制控制台的视图。请参阅设置控制台或位置和写入控制台等。

您需要在某些
对象上使用
锁来同时停止使用控制台的两个线程。声明如下内容:

public static class ThreadSafeConsole
{
    private static object _lockObject = new object();

    public static void WriteLine(string str)
    {
        lock (_lockObject) 
        {
            Console.WriteLine(str);
        }
    }
}
Save the current input buffer. Cancel the current asynchronous read. Reset the cursor position to the end of the last writing of new data. Output the new data. Save the cursor position. Restart the asynchronous read event.
现在调用
ThreadSafeConsole.WriteLine
而不是
Console.WriteLine
,我相信在标准的.NET控制台API中,使用一些黑客技术,这实际上是可能的。您需要做的是创建一个异步读取/读取行方法(根据您的帖子判断,我假设您已经这样做了),并允许在新数据到达时立即取消该方法。我假设您现在正在逐行发送输入。“新数据处理程序”的伪代码可能如下所示:

public static class ThreadSafeConsole
{
    private static object _lockObject = new object();

    public static void WriteLine(string str)
    {
        lock (_lockObject) 
        {
            Console.WriteLine(str);
        }
    }
}
Save the current input buffer. Cancel the current asynchronous read. Reset the cursor position to the end of the last writing of new data. Output the new data. Save the cursor position. Restart the asynchronous read event. 保存当前输入缓冲区。 取消当前异步读取。 将光标位置重置为上次写入新数据的末尾。 输出新数据。 保存光标位置。 重新启动异步读取事件。 特别是,您需要处理和属性。通过直接与Win32 API控制台函数接口,您可能可以避免一些黑客行为,但这可能不值得费心


希望这能有所帮助。

如果我理解正确,您必须为您的应用程序定义“键入到控制台”的开头和结尾,以便您在锁定对象时仍能锁定该对象,而不是将侦听器线程中的消息插入到键入的文本中

public static Object consoleLock = new Object();
public static void Main(string[] args)
{
    lock (consoleLock)
    {
        // now nothing can write to the console (if it's trying to lock onto it)
        Console.WriteLine("Please Input Something");
        // read from console
    }
    // now, your separate thread CAN write to the console - without 
    // interrupting your input process
}

也许你可以向我们展示你当前代码的相关部分?我不太明白你想要什么,你能更明确一点吗?我相信我知道你想做什么,但我想说的是,如果我们不必在我们的答案中重写你当前的方法,这会有所帮助。这有什么好处?非常感谢,我将尝试控制台API Aproacht控制台类可能会工作,因为您可能可以使用MoveBufferArea和一些簿记来做您想要做的事情。console类并没有提供本机api的所有控制,尤其是一些缓冲区操作函数。您误解了我的意思,我正在尝试读取,而侦听线程可以在任何消息出现时写入。如果我采用你的方法,我就不能同时读写控制台。谢谢,你的问题令人费解!:)您需要同步对单个控制台的访问,或者您应该编写GUI而不是控制台应用程序。我需要它是控制台应用程序。很抱歉提出了这些难以理解的问题,但其他人似乎已经很好地理解了。谢谢,但当你已经详细控制了光标的位置时,你还没有编写一个控制台应用程序;您已经实现了使用GUI可以轻松完成的任务。GUI上的控制台应用程序的唯一真正意义在于具有简单的I/O流,用于与其他命令或文件之间的管道连接。它需要是控制台应用程序,我使用SSH连接到PC的控制台:|我想到了这一点,但我也认为存在一种更简单的方法。如果我找不到其他东西,这就是我要用的,非常感谢。@Toma:没问题。。。是啊,恐怕你不会再简单了。事实上,我之前也调查过同样的事情,明确的结论是没有直接的方法。如果您对任何实现细节都不清楚,请告诉我。无论您是想一次读/写每个字符,还是只想读/写整行字符(在读取回车键时发送数据),这种方法基本上都会起作用。如果我收到一封邮件,我仍然希望保留键入的邮件,但我不希望它与收到的邮件混淆,我希望它在最后一行保持完整。