我有2个线程:其中一个是不断向控制台输入一些值,让我们说每秒增加一个int值 - 所以控制台上的每一秒都是1,2,3 ......依此类推。
另一个线程正在等待用户输入 - 使用命令cin。
这是我的问题:当我开始输入内容时,当cout int值时,我的输入将从输入字段中删除,并使用int值放入控制台。因此,当我想输入“hello”时,它看起来像这样:
1
2
3
he4
l5
lo6
7
8
有没有办法阻止我的输入被放到控制台,而其他线程正在写入控制台?
FYI这是客户端的聊天应用程序所需要的 - 一个线程正在侦听消息并在消息进入后立即输出此消息,而另一个线程正在侦听用户输入以发送到服务器应用程序。 / p>
答案 0 :(得分:1)
通常终端本身会回显键入的键。您可以将其关闭并让您的程序回应它。这个问题将指导你如何做到Hide password input on terminal
然后你可以让一个线程来处理输出。
答案 1 :(得分:0)
如果你是一个缓慢的typer,那么问题的解决方案可以是,正如我所说,使它成为一个单独的线程,但这可能使应用程序只有在它发送后才能收到。
另一种方法是增加你的接收线程的睡眠时间,这会为你提供更多的时间来打字(不会中断)
答案 2 :(得分:0)
你可以制作一个GUI(如果你真的想在控制台中工作,可以使用ncurses)。这样就可以避免让线程共享std :: cout。
答案 3 :(得分:0)
我认为你可以用信号量来解决这个问题。当您收到传入消息时,请检查用户是否正在编写内容。如果他,你等到他完成打印信息。
答案 4 :(得分:0)
有没有办法阻止我的输入被放到控制台,而其他线程正在写入控制台?
反过来了。另一个线程不应该中断您输入内容的显示。
假设您输入了“Hel”,然后另一个线程会收到一条新消息。你是做什么?该如何显示?
完全禁用您键入的内容的回显,并在您按Enter后显示它。通过这种方式,您可以以原子方式正确显示来自不同线程的消息。最大的缺点是你无法看到你已输入的内容...... :(
您可以立即回复您键入的内容。当新消息进入时,您撤消“Hel”,打印新消息并再次在新行上打印“Hel”,然后您可以继续键入。可行,但有点难看。
您可以在单独的位置回显您输入的内容。也就是说,你以某种方式分割显示。在一个地方,您按顺序显示已发布/已接收的消息;并在另一个地方显示您正在键入的内容。您需要一个GUI或至少一些控制台库来执行此操作。这将是最好的解决方案,但由于库依赖性,可能最难移植到另一个操作系统。
在任何情况下,您需要一个(最好是内部)同步流,您可以安全地从不同的线程调用,并可以原子方式将字符串写入其中。也就是说,您需要编写自己的同步流类。
希望这有帮助。
答案 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
}
}