我有一个执行一些后台处理的多线程 C++ 插件,我需要让它定期回调到我在 NodeJS 服务器中编写的 Javascript 函数。
我知道这涉及使用 uv_async_send(),因为它需要在主线程中执行,但到目前为止我还没有弄清楚如何去做。
有没有我错过的简单示例?
最佳答案
最后,一旦我理解了 uv_* 函数的作用,这就不是太难了:
1) 在插件中公开一个函数以允许 Node 设置将定期回调的 Javascript cb 到:
Callback* cbPeriodic; // keep cbPeriodic somewhere
NAN_METHOD(setPeriodicCb) {
cbPeriodic = new Callback(info[0].As<Function>());
//...
}
2) 使用 uv_async_t
实例和一个函数初始化 UV,当我们的工作线程调用 uv_async_send()
时,UV 将在主线程中执行该函数/强>
uv_async_t async; // keep this instance around for as long as we might need to do the periodic callback
uv_loop_t* loop = uv_default_loop();
uv_async_init(loop, &async, asyncmsg);
void asyncmsg(uv_async_t* handle) {
// Called by UV in main thread after our worker thread calls uv_async_send()
// I.e. it's safe to callback to the CB we defined in node!
Nan::HandleScope scope;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
Local<Value> argv[] = { v8::String::NewFromUtf8(isolate, "Hello world") };
cbPeriodic->Call(1, argv);
}
3) 从工作线程调用 uv_async_send
,在我们需要执行周期性回调时传递上面的异步实例
uv_async_send(&async);
4) 最后,当我们不再需要再次执行回调时,清理一下:
uv_close((uv_handle_t*) &async, NULL);
附录:
自从我写了这个答案后,我遇到了其他问题,并最终学到了一些关于 libuv 的类(class)。为了完整起见,您应该了解:
除了
uv_async_send
之外,所有 libuv 函数都可以仅从主循环中调用线! (我曾看到它提到其他人不是线程安全的,但这种说法太弱了。)甚至,例如,必须调用uv_async_init
和uv_close
来自主循环线程。如果您的
uv_async_t
实例是动态分配的,请注意您可能不会释放内存,直到 uv_close 发出回调通知您这样做是安全的。
即:
auto async = new uv_async_t();
...
uv_close((uv_handle_t*)async, [](uv_handle_t* handle) {
delete handle;
});
关于javascript - 从多线程 C++ 插件回调 NodeJS Javascript 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36987273/