文本编辑器可以将每个按键从一个线程传递到另一个线程吗?
Is it OK for a text editor to pass each keypress from one thread to another?
我正在实现一个 Win32 控制台文本编辑器,它有一个内部消息队列,用于传递有关要重绘的区域、消息 to/from 插件等的信息。默认情况下,我更喜欢它是单线程的(如果没有发生任何需要额外线程的事情)。我正在考虑 2 种消息队列实现策略:
- 使用通用队列和 Win32 事件,因此我可以使用
WaitForMultipleObjectsEx
同时等待内部消息和用户输入,同时传递控制台输入句柄和事件句柄。在这种情况下,文本编辑器可以完全存在于单个线程中。
- 使用I/O 完成端口。在这种情况下,文本编辑器将需要至少两个线程,一个调用
GetQueuedCompletionStatus
来获取消息,另一个读取用户输入并通过 PostQueuedCompletionStatus
将其发送到队列。控制台输入句柄不能重叠和 WaitFor*
函数不接受完成端口作为可等待句柄的原因,因此不可能同时等待它们。就像在第一个设置中一样,当没有输入或事件时,两个线程都不会浪费 CPU 时间,但是每个按键都必须通过 IOCP 从一个线程传递到另一个线程。
哪种设计总体上更好?
通过 IOCP 传递每个按键的性能和延迟缺点对文本编辑器是否重要?
IOCP 的性能和延迟完全符合您的要求。然而,我不会将每次按键转换为 PostQueuedCompletionStatus。我宁愿 PostQueuedCompletionStatus 一次将多个按键排入队列,无论您从 ReadConsoleInput 获得多少。
我认为性能差异很小,任何一个都可以更快,具体取决于环境。而 WaitForMultipleObjects 更容易实现。
P.S。你确定你需要消息队列吗?你为什么不在任何线程中处理这些重绘请求/插件消息,使用例如要保护的关键部分(控制台输出+您的共享状态)?如果您的拥塞很低,例如 100Hz 消息 + 15Hz 按键,并且您将快速处理它们,这将使您的延迟比 IOCP 或任何其他队列更低:在低拥塞或短暂锁定的情况下,关键部分甚至不会切换到lock/unlock 的内核。这也将简化设计,您的主线程将在阻塞 ReadConsoleInput() 调用时休眠,在此之前无需 WaitFor..
我正在实现一个 Win32 控制台文本编辑器,它有一个内部消息队列,用于传递有关要重绘的区域、消息 to/from 插件等的信息。默认情况下,我更喜欢它是单线程的(如果没有发生任何需要额外线程的事情)。我正在考虑 2 种消息队列实现策略:
- 使用通用队列和 Win32 事件,因此我可以使用
WaitForMultipleObjectsEx
同时等待内部消息和用户输入,同时传递控制台输入句柄和事件句柄。在这种情况下,文本编辑器可以完全存在于单个线程中。 - 使用I/O 完成端口。在这种情况下,文本编辑器将需要至少两个线程,一个调用
GetQueuedCompletionStatus
来获取消息,另一个读取用户输入并通过PostQueuedCompletionStatus
将其发送到队列。控制台输入句柄不能重叠和WaitFor*
函数不接受完成端口作为可等待句柄的原因,因此不可能同时等待它们。就像在第一个设置中一样,当没有输入或事件时,两个线程都不会浪费 CPU 时间,但是每个按键都必须通过 IOCP 从一个线程传递到另一个线程。
哪种设计总体上更好?
通过 IOCP 传递每个按键的性能和延迟缺点对文本编辑器是否重要?
IOCP 的性能和延迟完全符合您的要求。然而,我不会将每次按键转换为 PostQueuedCompletionStatus。我宁愿 PostQueuedCompletionStatus 一次将多个按键排入队列,无论您从 ReadConsoleInput 获得多少。
我认为性能差异很小,任何一个都可以更快,具体取决于环境。而 WaitForMultipleObjects 更容易实现。
P.S。你确定你需要消息队列吗?你为什么不在任何线程中处理这些重绘请求/插件消息,使用例如要保护的关键部分(控制台输出+您的共享状态)?如果您的拥塞很低,例如 100Hz 消息 + 15Hz 按键,并且您将快速处理它们,这将使您的延迟比 IOCP 或任何其他队列更低:在低拥塞或短暂锁定的情况下,关键部分甚至不会切换到lock/unlock 的内核。这也将简化设计,您的主线程将在阻塞 ReadConsoleInput() 调用时休眠,在此之前无需 WaitFor..