【问题标题】:C# Console: Write while reading and retain structureC# 控制台:边读边写并保留结构
【发布时间】:2009-05-23 17:16:25
【问题描述】:

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

当我键入时控制台会显示此内容并有消息进入:

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

我希望它像这样将我的消息与服务器消息分开:

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

如果我收到一条消息,我仍想保留我输入的消息,但我不希望它与收到的消息混淆,我希望它在最后一行保持完整。

我可以这样做吗?怎么做?

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

【问题讨论】:

  • 也许您可以向我们展示您当前代码的相关部分?
  • 我不太明白你在问什么,你能更明确一点吗?
  • 我相信我知道你想要做什么,但我想说的是,如果我们不必在我们的答案中重写你当前的大部分方法,那将会有所帮助。跨度>

标签: c# multithreading console client-server


【解决方案1】:

我相信这实际上可以通过标准的 .NET 控制台 API 使用,使用一点hacky。您需要做的是创建一个异步 Read/ReadLine 方法(我假设您已经完成了,根据您的帖子判断)并允许在新数据到达时立即取消它。我现在假设您正在逐行发送输入。 “新数据处理程序”的伪代码可能是这样的:

保存当前输入缓冲区。 取消当前的异步读取。 将光标位置重置到最后一次写入新数据的末尾。 输出新数据。 保存光标位置。 重新启动异步读取事件。

特别是,您需要处理Console.CursorLeftConsole.CursorTop 属性。您也许可以通过直接与 Win32 API 控制台函数交互来避免一些的黑客行为,但这可能不值得费心。

希望对您有所帮助。

【讨论】:

  • 我想到了这个,但我也认为存在一种更简单的方法。如果我找不到其他任何东西,这就是我将使用的,非常感谢。
  • @Toma:没问题...而且是的,恐怕你不会得到任何更简单的东西。实际上,我不久前曾研究过同样的事情,明确的结论是没有直接的方法。
  • 如果您不清楚任何实施细节,请告诉我。无论您是想一次读取/写入每个字符还是只读取整行(在读取 Enter 键时发送数据),此方法基本上都可以工作。
【解决方案2】:

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

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

2) 直接 P/Invoke 到 console API。这使您可以逐点完全控制控制台的视图。参见 SetConsoleCursorPosition 和 WriteConsole 等。

【讨论】:

  • 它提供了什么而不是这个不提供? msdn.microsoft.com/en-us/library/…
  • 非常感谢,我会试试 Console API 方法
  • Console 类可能会起作用,因为您可以使用 MoveBufferArea 和一些簿记来做您想做的事情。但是,控制台类并没有提供对本机 api 的所有控制,尤其是一些缓冲区操作函数。
【解决方案3】:

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

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

    public static void WriteLine(string str)
    {
        lock (_lockObject) 
        {
            Console.WriteLine(str);
        }
    }
}

现在调用ThreadSafeConsole.WriteLine 而不是Console.WriteLine

【讨论】:

  • 你误会了我,我正在尝试阅读,而监听线程可以在消息到来时写入。如果我采用您的方法,我将无法同时读取和写入控制台。谢谢
  • 那你的问题是不可理解的! :) 要么您需要同步对单个控制台的访问,要么您应该编写一个 GUI 而不是控制台应用程序。
  • 我需要它成为一个控制台应用程序。对不起,无法理解的问题,但其他人似乎已经理解它了。谢谢
  • 但是当您已经对光标位置进行了详细控制时,您还没有编写控制台应用程序;您已经重新实现了使用 GUI 可以更轻松地完成的工作。控制台应用程序在 GUI 上的唯一真正意义是拥有简单的 I/O 流,用于与其他命令或文件进行管道传输。
  • 它需要是一个控制台应用程序,我使用SSH连接到PC的控制台。 :|
【解决方案4】:

如果我理解正确,您必须为您的应用程序定义“键入控制台”的开头和结尾,以便在发生这种情况时您仍然可以锁定对象,而不是从您的侦听器线程进入您输入的文本。

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
}

【讨论】:

  • 您好,很抱歉让您感到困惑,我编辑了我的问题。如果我收到一条消息,我仍然想保留我输入的消息,但我不希望它与收到的消息混淆,我希望它在最后一行保持完整。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多