6

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

控制台在我输入时显示此信息,并出现一条消息:

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

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

来自服务器
的味精 来自服务器的
味精 来自服务器的味精
我的味精到服务器

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

我可以这样做吗?如何?

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

4

4 回答 4

3

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

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

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

希望有帮助。

于 2009-05-23T17:37:21.460 回答
1

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

1)把它变成一个GUI应用程序,并有单独的输入/输出区域。这是用户 POV 中最“清晰”的选项,但需要 GUI 应用程序而不是控制台应用程序。

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

于 2009-05-23T17:21:20.237 回答
1

您需要使用 a lockon someobject同时停止使用控制台的两个线程。声明如下:

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.

于 2009-05-23T17:33:54.397 回答
0

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

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
}
于 2009-05-23T17:39:49.847 回答