文本编辑器可以将每个按键从一个线程传递到另一个线程吗?

Is it OK for a text editor to pass each keypress from one thread to another?

我正在实现一个 Win32 控制台文本编辑器,它有一个内部消息队列,用于传递有关要重绘的区域、消息 to/from 插件等的信息。默认情况下,我更喜欢它是单线程的(如果没有发生任何需要额外线程的事情)。我正在考虑 2 种消息队列实现策略:

  1. 使用通用队列和 Win32 事件,因此我可以使用 WaitForMultipleObjectsEx 同时等待内部消息和用户输入,同时传递控制台输入句柄和事件句柄。在这种情况下,文本编辑器可以完全存在于单个线程中。
  2. 使用I/O 完成端口。在这种情况下,文本编辑器将需要至少两个线程,一个调用 GetQueuedCompletionStatus 来获取消息,另一个读取用户输入并通过 PostQueuedCompletionStatus 将其发送到队列。控制台输入句柄不能重叠和 WaitFor* 函数不接受完成端口作为可等待句柄的原因,因此不可能同时等待它们。就像在第一个设置中一样,当没有输入或事件时,两个线程都不会浪费 CPU 时间,但是每个按键都必须通过 IOCP 从一个线程传递到另一个线程。

哪种设计总体上更好?

通过 IOCP 传递每个按键的性能和延迟缺点对文本编辑器是否重要?

IOCP 的性能和延迟完全符合您的要求。然而,我不会将每次按键转换为 PostQueuedCompletionStatus。我宁愿 PostQueuedCompletionStatus 一次将多个按键排入队列,无论您从 ReadConsoleInput 获得多少。

我认为性能差异很小,任何一个都可以更快,具体取决于环境。而 WaitForMultipleObjects 更容易实现。

P.S。你确定你需要消息队列吗?你为什么不在任何线程中处理这些重绘请求/插件消息,使用例如要保护的关键部分(控制台输出+您的共享状态)?如果您的拥塞很低,例如 100Hz 消息 + 15Hz 按键,并且您将快速处理它们,这将使您的延迟比 IOCP 或任何其他队列更低:在低拥塞或短暂锁定的情况下,关键部分甚至不会切换到lock/unlock 的内核。这也将简化设计,您的主线程将在阻塞 ReadConsoleInput() 调用时休眠,在此之前无需 WaitFor..