在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事件循环。
如何以不会阻止v8的方式提取Windows消息,并允许我在窗口收到消息时调用JS函数?
我认为libuv会扮演一个角色,但我不确定如何从一个单独的线程上运行的C安全地调用JS函数,特别是从uv_async_send
is not guaranteed to invoke a callback every time you call it开始,我需要确保我的JS回调是每次收到窗口消息时都会调用。
答案 0 :(得分:11)
我的错误是试图在V8线程上创建窗口。相反,uv_thread_create
应该用于调用在新线程上创建窗口的函数,然后继续执行自己的消息泵循环。
然后,wndproc函数需要以线程安全的方式将收到的消息保存到队列中,然后使用uv_async_send
通知V8线程消息已到达。
然后在消息入队后调用V8线程上的函数(传递给uv_async_init
)。该函数(线程安全地)将每个待处理消息从队列中弹出并调用JS回调。
答案 1 :(得分:1)
我需要对requires a message pump的佳能EDSDK进行此操作。
libuv的uv_idle_t
是一个很好的选择:
尽管名称如此,但空闲句柄将在每次循环迭代时调用其回调,而不是在循环实际上是“空闲”时
示例:
#include <uv.h>
uv_idle_t* idle = new uv_idle_t();
uv_idle_init(uv_default_loop(), idle);
uv_idle_start(idle, idle_winmsg);
void idle_winmsg (uv_idle_t* idle) {
MSG msg;
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
答案 2 :(得分:0)
我找到了这个的真正原因。
Node.js事件循环将陷入对I / O的轮询,并且鉴于没有待处理的未完成I / O操作,事件循环将进入睡眠状态。
idle
和prepare
在Node.js事件循环执行的I / O轮询之前运行,但是没有安排任何工作,您最多只能看到1或2个回调。>
没有解决方案,因为没有Win32消息API可用于向I / O完成端口发出信号。您必须在单独的线程中运行Win32消息循环。