N-API C++ 插件导致 Electron GUI 阻塞
N-API C++ addon causing Electron GUI to block
我有一个 N-API C++ 插件,我想将它与 Electron GUI 一起使用。目前,C++ 插件有一个简单的函数,可以休眠 10 秒,然后执行 8*2 的计算,并将 returns 的值传递给 Javascript 代码。 Javascript 代码 运行 每 10 秒发送一次 C++ 插件。
// index.js
const addon = require('./build/Release/module');
const electron = require('electron');
const {app, BrowserWindow} = require('electron');
let win;
function createWindow() {
win = new BrowserWindow({width: 800, height: 600});
win.loadFile('./index.html');
win.on('closed', () => {win = null});
}
app.on('ready', createWindow);
app.on('activate', () => {
if (win === null) {
createWindow();
}
})
function getInfoFromNativeModule() {
const value = 8;
console.log(`${value} times 2 equals`, addon.my_function(value));
setTimeout(getInfoFromNativeModule, 1000);
}
getInfoFromNativeModule();
然而,当我 运行 上述代码时,我发现原生 C++ 插件导致 Electron GUI 阻塞 10 秒,每次 运行s。有什么方法可以让我在后台执行繁重的计算并且让 Electron GUI 不被阻塞或冻结?我假设我必须使用某种线程,但我不确定如何使用 N-API 来实现。下面是我的其余文件,包括 module.cpp 和 package.json 文件。
// module.cpp
napi_value MyFunction(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc = 1;
int number = 0;
napi_value argv[1];
status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to parse arguments");
}
status = napi_get_value_int32(env, argv[0], &number);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Invalid number was passed as argument");
}
napi_value myNumber;
number = number * 2;
std::cout << "sleeping for 10 seconds" << std::endl;
sleep(10);
std::cout << "waking up" << std::endl;
status = napi_create_int32(env, number, &myNumber);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Unable to create return value");
}
return myNumber;
}
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_value fn;
status = napi_create_function(env, NULL, 0, MyFunction, NULL, &fn);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Unable to wrap native function");
}
status = napi_set_named_property(env, exports, "my_function", fn);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Unable to populate exports");
}
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
// package.json
{
"name": "n-api-article",
"version": "0.1.0",
"main": "index.js",
"scripts": {
"start": "node-gyp rebuild && electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/schahriar/n-api-article.git"
},
"engines": {
"node": ">=8.4.0"
},
"dependencies": {
"electron": "^4.0.8",
"electron-rebuild": "^1.8.4"
}
}
它阻止 Electron 的原因是 sleep(10)
。该呼叫不会 return 10 秒。
所以是的,有一种方法可以将繁重的计算卸载到另一个线程。这样做最大的复杂性是线程无法在不采取额外预防措施的情况下对 JavaScript 进行回调,线程也无法访问 JavaScript 数据结构,因此必须为其提供所有必要的数据。
这是 C++ 抽象为 N-API 使用线程计算 Pi 提供的示例。
这里是用于创建线程安全回调的 C++ 包装器。
这不是微不足道的,但这两个示例应该可以帮助您完成它。
我有一个 N-API C++ 插件,我想将它与 Electron GUI 一起使用。目前,C++ 插件有一个简单的函数,可以休眠 10 秒,然后执行 8*2 的计算,并将 returns 的值传递给 Javascript 代码。 Javascript 代码 运行 每 10 秒发送一次 C++ 插件。
// index.js
const addon = require('./build/Release/module');
const electron = require('electron');
const {app, BrowserWindow} = require('electron');
let win;
function createWindow() {
win = new BrowserWindow({width: 800, height: 600});
win.loadFile('./index.html');
win.on('closed', () => {win = null});
}
app.on('ready', createWindow);
app.on('activate', () => {
if (win === null) {
createWindow();
}
})
function getInfoFromNativeModule() {
const value = 8;
console.log(`${value} times 2 equals`, addon.my_function(value));
setTimeout(getInfoFromNativeModule, 1000);
}
getInfoFromNativeModule();
然而,当我 运行 上述代码时,我发现原生 C++ 插件导致 Electron GUI 阻塞 10 秒,每次 运行s。有什么方法可以让我在后台执行繁重的计算并且让 Electron GUI 不被阻塞或冻结?我假设我必须使用某种线程,但我不确定如何使用 N-API 来实现。下面是我的其余文件,包括 module.cpp 和 package.json 文件。
// module.cpp
napi_value MyFunction(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc = 1;
int number = 0;
napi_value argv[1];
status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to parse arguments");
}
status = napi_get_value_int32(env, argv[0], &number);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Invalid number was passed as argument");
}
napi_value myNumber;
number = number * 2;
std::cout << "sleeping for 10 seconds" << std::endl;
sleep(10);
std::cout << "waking up" << std::endl;
status = napi_create_int32(env, number, &myNumber);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Unable to create return value");
}
return myNumber;
}
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_value fn;
status = napi_create_function(env, NULL, 0, MyFunction, NULL, &fn);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Unable to wrap native function");
}
status = napi_set_named_property(env, exports, "my_function", fn);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Unable to populate exports");
}
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
// package.json
{
"name": "n-api-article",
"version": "0.1.0",
"main": "index.js",
"scripts": {
"start": "node-gyp rebuild && electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/schahriar/n-api-article.git"
},
"engines": {
"node": ">=8.4.0"
},
"dependencies": {
"electron": "^4.0.8",
"electron-rebuild": "^1.8.4"
}
}
它阻止 Electron 的原因是 sleep(10)
。该呼叫不会 return 10 秒。
所以是的,有一种方法可以将繁重的计算卸载到另一个线程。这样做最大的复杂性是线程无法在不采取额外预防措施的情况下对 JavaScript 进行回调,线程也无法访问 JavaScript 数据结构,因此必须为其提供所有必要的数据。
这是 C++ 抽象为 N-API 使用线程计算 Pi 提供的示例。
这里是用于创建线程安全回调的 C++ 包装器。
这不是微不足道的,但这两个示例应该可以帮助您完成它。