【问题标题】:Why does blocked IO in another thread prevent CreateWindowEx() from returning为什么另一个线程中的阻塞 IO 会阻止 CreateWindowEx() 返回
【发布时间】:2015-07-07 12:06:55
【问题描述】:

我有一个非常简单的 Windows 控制台应用程序,它首先创建一个线程来处理标准输入上的输入。它使用main()中的CreateThread()创建线程,线程做的第一件事就是调用getchar()并阻塞,等待。

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

但是CreateWindowEx() 永远不会回来。

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

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

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

【问题讨论】:

  • 你的窗口过程发生了什么?你收到WM_NC_CREATE了吗?
  • 窗口过程只调用 DefWindowProc() ,除非它是 WM_USER 消息,在这种情况下它会将其记录到文件中。如果我不在线程中调用 getchar() ,这将有效。我不知道是否正在向它发送 WM_NC_CREATE。
  • 可以提供an MCVE吗?

标签: windows multithreading winapi io nonblocking


【解决方案1】:

C 运行时库不正式支持从使用CreateThread 生成的线程调用。您应该使用诸如_beginthreadex 之类的 CRT 包装函数,它们会在新线程上正确配置 CRT 线程本地状态。

在实践中,即使您违反了该规则,CRT 也会竭尽全力让事情正常进行,但细节取决于您是静态链接还是动态链接 CRT(因为这会影响是否存在 THREAD_ATTACH 回调)。

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

【讨论】:

  • 感谢您的洞察力,本。我尝试快速更改线程代码以使用 _beginthread() 并没有产生任何影响。它仍然挂在 CreateWindowEx() 中。我还尝试让 ReadConsole() 改为工作,但这被证明具有挑战性。我不确定为什么它还没有工作。
  • 我无法使用 _beginthreadex() 使其工作,但最终能够通过使用 ReadFile() 和 WriteFile() 替换所有 stdio 函数来使其工作。谢谢本!
  • @Nicholas:不客气。是的,如果您只对字符数据感兴趣,ReadFile 是一个不错的 I/O 选择,包括控制台 I/O。 ReadConsole 还提供字符数据(键盘和剪贴板)以及鼠标。
猜你喜欢
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 2021-10-19
  • 2021-08-29
  • 1970-01-01
  • 2015-04-27
  • 2015-06-25
相关资源
最近更新 更多