2

我有 2 个线程:其中一个线程不断地向控制台输出一些值,假设每秒增加一个 int 值 - 所以控制台上的每一秒都是 1、2、3 ......等等。

另一个线程正在等待用户输入 - 使用命令 cin。

这是我的问题:当我开始输入内容时,当需要计算 int 值时,我的输入会从输入字段中删除,并与 int 值一起放入控制台。所以当我想输入“hello”时,它看起来像这样:

1
2
3
he4
l5
lo6
7
8

有没有办法防止我的输入被放到控制台,而其他线程正在写入控制台?

仅供参考,这是客户端聊天应用程序所需要的 - 一个线程正在侦听消息并在消息进入时立即输出此消息,而另一个线程正在侦听要发送到服务器应用程序的用户输入。

4

6 回答 6

1

通常终端本身会回显键入的键。您可以将其关闭并让您的程序回显它。这个问题将为您提供有关如何操作的指示在终端上隐藏密码输入

然后,您可以只使用一个线程来处理输出。

于 2013-08-10T09:48:02.520 回答
0

我认为你可以用信号量解决这个问题。当您收到传入消息时,您会检查用户是否在写东西。如果他这样做,请等到他完成打印消息。

于 2013-08-10T09:56:40.967 回答
0

如果您是一个慢速打字机,那么解决问题的方法可以是,正如我所说,将其设为单线程,但这可能会使应用程序仅在发送后才能接收。

另一种方法是增加接收线程的睡眠时间,这将为您提供更多输入时间(不中断)

于 2013-08-10T09:42:02.370 回答
0

您可以制作一个 GUI(如果您真的想在控制台中工作,也可以使用 ncurses)。这样可以避免线程共享 std::cout。

于 2013-08-10T09:43:28.447 回答
0

有没有办法防止我的输入被放到控制台,而其他线程正在写入控制台?

情况恰恰相反。另一个线程不应中断您正在输入的内容的显示。

假设您输入了“Hel”,然后从另一个线程输入了一条新消息。你做什么工作?应该如何显示?

  1. 完全禁用回显您键入的内容,仅在您按 Enter 后显示。通过这种方式,您可以以原子方式正确显示来自不同线程的消息。最大的缺点是你看不到你已经输入的内容...... :(

  2. 您会立即回显您键入的内容。当新消息出现时,您撤消“Hel”,打印新消息并在新行上再次打印“Hel”,您可以继续输入。可行但有点难看。

  3. 您在单独的位置回显您键入的内容。也就是说,您以某种方式拆分了显示。在一个地方,您按顺序显示发布/接收的消息;在另一个地方显示你正在输入的内容。您要么需要一个 GUI,要么至少需要一些控制台库来执行此操作。这将是最好的解决方案,但由于库依赖关系,可能是最难移植到另一个操作系统的解决方案。

在任何情况下,您都需要一个(最好是内部的)同步流,您可以安全地从不同的线程调用它,并且可以将字符串原子地写入其中。也就是说,你需要编写自己的同步流类。

希望这可以帮助。

于 2013-08-10T12:18:25.533 回答
0

好吧,我最近用一个基本的解决方法解决了同样的问题。这可能不是#1解决方案,但对我来说就像一个魅力,作为一个新手;

 #include <iostream>    // I/O
 #include <Windows.h>   // Sleep();
 #include <conio.h>     // _getch();
 #include <string>      // MessageBuffer
 #include <thread>      // Thread
 using namespace std;

 void ThreadedOutput();
 string MessageBuffer;  // or make it static

 void main()
 {
    thread output(ThreadedOutput); // Attach the output thread
    int count = 0;
    char cur = 'a'; // Temporary at start
    while (cur != '\r')
    {
        cur = _getch(); // Take 1 input
        if (cur >= 32 && cur <= 126) // Check if input lies in alphanumeric and special keys
        {
            MessageBuffer += cur; // Store input in buffer
            cout << cur; // Output the value user entered
            count++;
        }
        else if (cur == 8) // If input key was backspace
        {
            cout << "\b \b"; // Move cursor 1 step back, overwrite previous character with space, move cursor 1 step back
            MessageBuffer = MessageBuffer.substr(0, MessageBuffer.size() - 1); // Remove last character from buffer
            count--;
        }
        else if (cur == 13) // If input was 'return' key
        {
            for (int i = 0; i < (signed)MessageBuffer.length(); i++) // Remove the written input
                cout << "\b \b";
            // "MessageBuffer" has your input, use it somewhere
            MessageBuffer = ""; // Clear the buffer
        }
     }
     output.join(); // Join the thread
 }

 void ThreadedOutput()
 {
    int i = 0;
    while (true)
     {
        for (int i = 0; i < (signed)MessageBuffer.length(); i++) // Remove the written input
            cout << "\b \b";
        cout << ++i << endl; // Give parallel output with input
        cout << MessageBuffer; // Rewrite the stored buffer
        Sleep(1000); // Prevent this example spam
     }
 }
于 2017-11-22T14:33:53.937 回答