В аддоне Windows nodejs я создал окно для получения сообщений.
Handle<Value> MakeMessageWindow(const Arguments &args) { // exposed to JS
...
CreateWindow(L"ClassName", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
...
}
У меня есть функция wndproc.
Local<Function> wndProc;
LRESULT APIENTRY WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
// pack up the arguments into Local<Value> argv
wndProc->Call(Context::GetCurrent()->Global(), 3, argv);
}
Теперь мне нужно прокачать сообщения. Обычно вы делаете что-то вроде
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
…но это не сработает, так как это просто заблокирует цикл обработки событий v8.
Как я прокачиваю сообщения Windows таким образом, чтобы не блокировать v8 и позволить мне вызывать функцию JS, когда мое окно получает сообщения?
Я предполагаю, что libuv сыграет свою роль, но я точно не знаю, как безопасно вызвать функцию JS из C, работающую в отдельном потоке, особенно если uv_async_send
не гарантированно вызывать обратный вызов каждый раз, когда вы звоните, и я должен убедиться, что мой обратный вызов JS вызывается каждый раз, когда получено оконное сообщение.
Моя ошибка была в попытке создать окно в потоке V8. Вместо, uv_thread_create
должен использоваться для вызова функции, которая создает окно в новой теме и затем приступает к выполнению собственного цикла прокачки сообщений.
Затем функция wndproc должна сохранять полученные сообщения в очередь потокобезопасным способом, а затем использовать uv_async_send
уведомить поток V8 о том, что сообщения пришли.
Функция в потоке V8 (которая была передана uv_async_init
) затем вызывается после помещения сообщений в очередь. Функция (поточно-ориентированная) выталкивает каждое ожидающее сообщение из очереди и вызывает обратный вызов JS.
Я нашел фактическую причину этого.
Цикл событий Node.js застревает при опросе для ввода-вывода, и, поскольку нет ожидающих ожидающих операций ввода-вывода, цикл обработки переходит в спящий режим.
idle
а также prepare
выполняются до опроса ввода / вывода, который выполняется циклом событий Node.js, но без запланированной работы вы можете увидеть, в лучшем случае, 1 или 2 обратных вызова.
Решение этой проблемы не существует, поскольку отсутствует API сообщений Win32, который можно использовать для сигнализации о завершении порта ввода / вывода. Вы должны запустить цикл сообщений Win32 в отдельном потоке.