У меня есть RPC-сервер Cap’n Proto, который запускает некоторые команды OpenGL в окне. Меня вообще не интересуют события окна, но чтобы избежать гибели в Windows, мне нужно опрашивать события раз в секунду или около того. Как я могу сделать это простым способом?
Я читал, что вы можете создать свой собственный EventPort, но я не мог понять, как на самом деле использовать EventPort. Это также может быть излишним, когда я на самом деле не заинтересован в событиях. Я хотел бы расставить приоритеты событий RPC над опросом окна, если это возможно.
Использование чего-то другого, кроме EZ-rpc, не является недостатком, так как я хочу перейти к общему использованию памяти позже.
Итак, в обработке событий Windows есть один критический недостаток: лучший способ обработки сетевых операций ввода-вывода, особенно со многими соединениями, — через порты завершения ввода-вывода (IOCP). Однако, к сожалению, Windows не предоставляет потоку возможности ожидать событий IOCP и событий GUI в одном потоке. Кажется, это серьезный недостаток в Win32 API, но так было десятилетиями. Еще более странно, что внутренние API-интерфейсы ядра NT фактически поддерживают альтернативу (в частности, они позволяют доставлять события завершения ввода-вывода через APC), но Microsoft не сделала эти API-интерфейсы общедоступными, поэтому приложения, которые их используют, могут сломаться в будущем. версия винды.
В результате есть два основных способа разработки программы, которая одновременно выполняет сетевой ввод-вывод и реализует графический интерфейс:
Использовать MsgWaitForMultipleObjectsEx
цикл событий на основе вместо IOCP. Вы будете ограничены не более чем 64 соединениями, и цикл обработки событий будет относительно неэффективным.
Есть отдельные темы для сети и графического интерфейса.
Для вашего случая использования, похоже, что # 1, вероятно, будет хорошо, но есть еще одна проблема: библиотека цикла событий KJ (используемая Cap’n Proto) пока не реализует этот случай. Он реализует только IOCP-сети. Там есть класс Win32WaitObjectThreadPool
определяется в kj/async-win32.h
предназначен для обработки цикла событий GUI … но в настоящее время он не реализован. (PR приветствуются, если вы хотите внести свой вклад!)
Если вы действительно не заботитесь о своевременной обработке событий GUI, то, возможно, сработает хак: вы можете использовать kj::Timer
создать цикл, который ждет секунду, затем проверяет очередь событий Win32 GUI, затем снова ждет и так далее. Это действительно некрасиво, но, вероятно, будет легко осуществить. Я не уверен, если kj::Timer
выставляется через EZ-rpc, поэтому вам, возможно, придется перейти на строительные блоки более низкого уровня, такие как kj::setupAsyncIo()
вместо.
Других решений пока нет …