如何在其他线程输出到控制台时防止输入文本中断?

时间:2013-08-10 09:20:01

标签: c++ c multithreading

我有2个线程:其中一个是不断向控制台输入一些值,让我们说每秒增加一个int值 - 所以控制台上的每一秒都是1,2,3 ......依此类推。

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

这是我的问题:当我开始输入内容时,当cout int值时,我的输入将从输入字段中删除,并使用int值放入控制台。因此,当我想输入“hello”时,它看起来像这样:

1
2
3
he4
l5
lo6
7
8

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

FYI这是客户端的聊天应用程序所需要的 - 一个线程正在侦听消息并在消息进入后立即输出此消息,而另一个线程正在侦听用户输入以发送到服务器应用程序。 / p>

6 个答案:

答案 0 :(得分:1)

通常终端本身会回显键入的键。您可以将其关闭并让您的程序回应它。这个问题将指导你如何做到Hide password input on terminal

然后你可以让一个线程来处理输出。

答案 1 :(得分:0)

如果你是一个缓慢的typer,那么问题的解决方案可以是,正如我所说,使它成为一个单独的线程,但这可能使应用程序只有在它发送后才能收到。

另一种方法是增加你的接收线程的睡眠时间,这会为你提供更多的时间来打字(不会中断)

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

  

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

反过来了。另一个线程不应该中断您输入内容的显示。

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

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

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

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

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

    希望这有帮助。

答案 5 :(得分:0)

我最近用基本的解决方法解决了同样的问题。这可能不是排名第一的解决方案,但对我来说就像一个新手一样迷人;

 #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
     }
 }