2015-04-28 207 views
2

我有一个非常简单的Windows控制台应用程序,它首先创建一个线程来处理stdin上的输入。它使用CreateThread()中的main()来创建线程,线程所做的第一件事情是调用getchar()并阻止,等待。为什么在另一个线程中阻塞的IO阻止CreateWindowEx()返回

然后main()使用RegisterClass()注册一个窗口类并调用CreateWindowEx()来创建一个不可见的消息窗口。

但是CreateWindowEx()永不退货。

如果我删除线程中的getchar()并将其替换为while (1) Sleep(1000);,则一切正常。

如果我将Sleep(1000);添加到线程函数的开头,CreateWindowEx()调用成功,但线程中的I/O停止工作(getchar()不返回)。

为什么被阻塞的第二个线程会干扰第一个线程?

+0

你的窗口过程发生了什么?你收到了“WM_NC_CREATE”吗? –

+0

窗口过程只是调用DefWindowProc(),除非它是WM_USER消息,在这种情况下,它会将该消息记录到文件中。如果我不在线程中调用getchar(),这将起作用。我不知道WM_NC_CREATE是否正在发送给它。 – Nicholas

+2

你能提供[一个MCVE](http://stackoverflow.com/help/mcve)吗? –

回答

2

C运行时库不正式支持从CreateThread生成的线程调用。您应该使用CRT包装功能,例如_beginthreadex,它可以在新线程上正确配置CRT线程本地状态。

实际上,即使违反了规则,CRT也会竭尽全力让其工作,但细节取决于您是否静态或动态地与CRT连接(因为这会影响是否存在回调THREAD_ATTACH) 。

尝试通过仅在_beginthreadex开始的线程上进行CRT调用来做到“正确”。 (一种方法是继续使用CreateThread,然后在工作线程中使用ReadConsole而不是getchar,另一种方法是使用_beginthreadex而不是CreateThread)。

+0

谢谢你的见解,本。我试着快速改变线程代码来使用_beginthread(),但它没有什么区别。它仍然挂在CreateWindowEx()中。我还修改了ReadConsole()来代替工作,但事实证明这很具有挑战性。我不确定它为什么还没有工作。 – Nicholas

+0

我无法使用_beginthreadex()获得此工作,但最终能够通过使用ReadFile()和WriteFile()来替换所有stdio函数来使其工作。谢谢Ben! – Nicholas

+0

@尼古拉斯:不客气。是的,如果你只对字符数据感兴趣,'ReadFile'对I/O来说是一个不错的选择,包括控制台I/O。 'ReadConsole'提供字符数据(键盘和剪贴板)以及鼠标。 –