我希望能够在输入时输出信息。 例如:每秒打印一行,但也取消用户输入......
我试过了:
#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
using namespace std;
void foo()
{
while(1)
{
usleep(1000000);
cout << "Cake\n";
}
}
int main()
{
thread t1(foo);
t1.join();
string x;
while(1)
{
cin >> x;
cout << x << "\n";
}
return 0;
}
哪个输出:
蛋糕
蛋糕
蛋糕
然后我开始输入:
hiCake
当我希望它是:
蛋糕
喜
&#39; hi&#39;仍然在输入
如果这不可能,在输入文字时,至少有一种方法可以暂停输出吗?
我在Windows 7上使用C ++ 11,使用CygWin作为Unix库
MUTEX TESTS
输出循环锁定:
#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
#include <mutex>
using namespace std;
mutex mtx;
void foo()
{
mtx.lock();
while(1)
{
usleep(1000000);
cout << "Cake\n";
}
mtx.unlock();
}
int main()
{
thread t1(foo);
t1.join();
string x;
while(1)
{
cin >> x;
cout << x << "\n";
}
return 0;
}
输入循环锁定:
#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
#include <mutex>
using namespace std;
mutex mtx;
void foo()
{
while(1)
{
usleep(1000000);
cout << "Cake\n";
}
}
int main()
{
thread t1(foo);
t1.join();
string x;
mtx.lock();
while(1)
{
cin >> x;
cout << x << "\n";
}
mtx.unlock();
return 0;
}
纯输出锁定:
#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
#include <mutex>
using namespace std;
mutex mtx;
void foo()
{
while(1)
{
mtx.lock();
usleep(1000000);
cout << "Cake\n";
mtx.unlock();
}
}
int main()
{
thread t1(foo);
t1.join();
string x;
while(1)
{
cin >> x;
cout << x << "\n";
}
return 0;
}
纯输入锁定:
#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
#include <mutex>
using namespace std;
mutex mtx;
void foo()
{
while(1)
{
usleep(1000000);
cout << "Cake\n";
}
}
int main()
{
thread t1(foo);
t1.join();
string x;
while(1)
{
mtx.lock();
cin >> x;
mtx.unlock();
cout << x << "\n";
}
return 0;
}
为了节省空间,我不会粘贴更多代码;我做了其他测试,我做了mutex mtx2
并试图锁定输入(mtx
)和输出(mtx2
)(纯和循环)。我也尝试用mtx
(再次,纯粹和循环)
答案 0 :(得分:2)
使用互斥锁保护代码的关键部分 - 请参阅http://www.cplusplus.com/reference/mutex/mutex/
答案 1 :(得分:1)
使用pure output locked
的代码几乎是正确的解决方案。需要做的是使用互斥锁保护“cout”语句并在std::thread::join
中移动while
main
循环,否则永远不会执行:
using namespace std;
mutex mtx;
void foo()
{
while(1)
{
usleep(1000000);
mtx.lock(); // we want mutex to be held only for time of cout, not time of wait
cout << "Cake\n";
mtx.unlock();
}
}
int main()
{
thread t1(foo);
string x;
while(1)
{
mtx.lock(); // we lock second occurence of cout and cin not to get interrupted by foo
cin >> x;
cout << x << "\n";
mtx.unlock();
}
t1.join(); // thread join stops the calling thread until called thread is finished
// so we join the thread just before our program finishes
return 0;
}
通过这种方式,您将获得如下输出:
Cake
Hi
Hi
为什么我们在foo()
的时间内没有锁定usleep
?因为它会锁定互斥锁的时间超过必要的时间。
为什么我选择不在mtx
之前锁定cin
?因为cin
的时间非常不确定。如果foo()
正在执行任何重要操作,则可能会暂停很长时间。
我个人建议你阅读Anthony Williams的书C++ Concurrency in Action
。我认为很好看。
答案 2 :(得分:0)
使用&#34;打印&#34;同步对cout
的访问权限的对象:
struct SyncCOUT{
SyncCOUT(): m_mutex() {}
std::mutex m_mutex;
std::ostream & operator<<(const char * _str)
{
m_mutex.lock();
cout << _str;
m_mutex.unlock();
return cout;
}
};
SyncCOUT g_scout;
// and then in both threads use this global synchronized "cout" wrapper like this:
// g_scout << "Hello, world!\n";
答案 3 :(得分:0)
为此,您需要做一些事情:
创建两个线程,一个将在标准输出上写入文本,另一个将从标准输入中读取文本。
在写入之前使输出线程锁定mutex
,并在写入后将其解锁。此写作操作将是您的关键部分&#34;。
在 read 线程内,直接从终端读取字符数据。在Unix上,您可以使用curses
库来完成此任务(可能是getch()
函数),在Windows上,您可能会在从ReadFile
获取的句柄上使用GetStdHandle(STD_INPUT_HANDLE)
。
然后您可以创建一个简单的状态机:如果用户按下不是enter
的密钥,请尝试锁定mutex
。如果用户按下enter
键,请解锁mutex
。
这样,只有在用户按下enter
键后, write 线程才能输出文本。当用户处于输入文本的中间时(即按<{1}}键之前的),enter
将阻止写入操作,直到用户按下{{1密钥。
可能需要扩展此方法以处理按mutex
键。
答案 4 :(得分:0)
您可能需要通过调用std :: cout.flush()显式同步std :: cout。
这似乎是您正在运行的控制台的实现问题。某些控制台(如cmd.exe和powershell)在std :: cout上每次插入(&lt;&lt;&lt;&lt;&lt;)操作后都执行了隐式flush()同步。我担心我测试的线程代码有并发问题,直到我发现它在cmd.exe和powershell下正常工作,但不在MINGW64 / MSYS2下(Git for Windows部署)。
没有刷新调用我的两个线程没有按预期交错字符,实际上直到工作线程是.join()编辑时才输出字符,直到我添加了显式的std :: cout.flush()。在添加之后,所有三个控制台都具有相同的行为。