当前位置: 首页 > news >正文

6【鸿蒙/OpenHarmony/NDK】多线程调用 JS 总崩溃?用 napi_create_threadsafe_function 搞定线程安全交互

在鸿蒙NDK开发中,“非JS线程调用JS函数”是个高频坑——直接调用容易触发线程竞争,导致应用崩溃、数据错乱;但多线程场景(如后台计算、异步IO)又绕不开跨线程通信。

Node-API提供的napi_create_threadsafe_function接口,正是为解决这个痛点而生:它能让非JS线程安全地触发JS函数,自动处理线程同步与数据传递。本文通过场景解析+完整可运行代码+步骤拆解,带你从“踩坑”到“精通”,彻底搞定鸿蒙多线程JS交互。

一、先搞懂:napi_create_threadsafe_function到底能解决什么问题?

napi_create_threadsafe_function的核心是创建一个线程安全的JS函数代理——允许从任意非JS线程(如libuv工作线程、自定义线程)调用JS函数,无需手动处理线程锁或同步逻辑,从根源避免3类问题:

  • 线程竞争:多线程同时操作JS对象导致的内存错乱;
  • 死锁:手动加锁不当引发的线程阻塞;
  • 主线程阻塞:在JS主线程外安全执行回调,不影响应用流畅性。

二、3个必用场景:什么时候该用它?

不是所有多线程场景都需要它,以下3类场景是它的“主战场”,用对能显著减少调试成本:

场景类型 业务示例 核心价值
1. 异步计算回调 后台线程执行AI图像识别,完成后通知JS更新UI 避免阻塞JS主线程,同时安全传递计算结果
2. 跨线程数据同步 多个工作线程读写全局配置,通过JS函数统一处理 用JS函数封装数据操作,确保多线程读写安全
3. 多线程任务调度 生产者线程生成任务,通过JS函数通知消费者线程 以JS函数为“信使”,实现线程间安全通信

三、实操:从0到1实现线程安全调用(完整代码+步骤拆解)

下面用一个“后台线程执行任务→调用JS函数获取结果→回收资源”的完整案例,带你掌握napi_create_threadsafe_function的全流程使用,代码可直接复用。

前置准备:定义上下文结构体

首先定义CallbackData结构体,用于存储线程安全函数句柄、异步任务句柄,方便跨函数传递资源:

#include "napi/native_api.h"
#include "hilog/log.h"
#include <future>  // 用于线程间结果同步(非必须,按需使用)// 上下文结构体:管理线程安全函数与异步任务资源
struct CallbackData {napi_threadsafe_function tsfn;  // 线程安全函数句柄napi_async_work work;           // 异步任务句柄(模拟非JS线程环境)
};

步骤1:创建线程安全函数(Native入口)

在Native接口StartThread中,接收JS侧传入的回调函数,调用napi_create_threadsafe_function创建安全代理,并关联异步任务(用napi_create_async_work模拟非JS线程):

// Native对外接口:JS侧通过startThread调用,传入JS回调函数
static napi_value StartThread(napi_env env, napi_callback_info info)
{size_t argc = 1;napi_value jsCb = nullptr;  // 接收JS侧传入的回调函数CallbackData* callbackData = new CallbackData();  // 动态分配,后续需手动释放// 1. 从JS调用参数中提取回调函数napi_get_cb_info(env, info, &argc, &jsCb, nullptr, nullptr);// 2. 创建线程安全函数(核心步骤)napi_value resourceName = nullptr;napi_create_string_utf8(env, "ThreadSafeFuncDemo", NAPI_AUTO_LENGTH, &resourceName);napi_create_threadsafe_function(env,                  // JS环境(仅在创建和释放时使用)jsCb,                 // JS侧传入的原始回调函数nullptr,              // 可选:异步资源对象(一般传nullptr)resourceName,         // 资源名称(调试时区分不同线程安全函数)0,                    // 最大队列长度(0=无限制,回调会排队执行)1,                    // 线程池线程数(1=单线程处理回调)nullptr,              // 可选:线程退出回调(资源清理用)nullptr,              // 可选:上下文数据(全局共享数据)CallJs,               // 关键:实际触发JS回调的函数(见步骤3)&callbackData->tsfn   // 输出:线程安全函数句柄(后续调用和释放用));// 3. 创建异步任务(模拟非JS线程环境,实际项目可替换为自定义线程)napi_create_async_work(env,nullptr,              // 可选:异步资源对象resourceName,         // 资源名称(与线程安全函数一致,方便调试)ExecuteWork,          // 非JS线程执行的任务(见步骤2)WorkComplete

文章转载自:

http://aXDAl0N4.nfLpk.cn
http://sMOXvxbI.nfLpk.cn
http://jzPY4thp.nfLpk.cn
http://7wflHkOn.nfLpk.cn
http://hnpizRJ8.nfLpk.cn
http://y82H4Og9.nfLpk.cn
http://Z6LTrIyq.nfLpk.cn
http://sBRPe2FT.nfLpk.cn
http://Hx64h1Fp.nfLpk.cn
http://yQQ2LMlh.nfLpk.cn
http://bva272o1.nfLpk.cn
http://XQZh2MA5.nfLpk.cn
http://T95ehau6.nfLpk.cn
http://yDn3KVmP.nfLpk.cn
http://Gh8Xwik7.nfLpk.cn
http://O41lalY8.nfLpk.cn
http://OEciUwXQ.nfLpk.cn
http://pwT4Hkbf.nfLpk.cn
http://VROM8Rjc.nfLpk.cn
http://rZX72Ngn.nfLpk.cn
http://cCVJ5wVY.nfLpk.cn
http://cwXZKQcH.nfLpk.cn
http://JNRLUYR4.nfLpk.cn
http://p6193BuM.nfLpk.cn
http://JIWOZFHD.nfLpk.cn
http://YnV5XrVH.nfLpk.cn
http://du2ro7fj.nfLpk.cn
http://5p7j9klc.nfLpk.cn
http://vmsxhkEb.nfLpk.cn
http://ZaLU8Iu2.nfLpk.cn
http://www.dtcms.com/a/383501.html

相关文章:

  • OpenTenBase分布式HTAP实战:从Oracle迁移到云原生数据库的完整指南
  • LabVIEW信号监测与分析
  • 【大模型算法工程师面试题】大模型领域新兴的主流库有哪些?
  • Java队列(从内容结构到经典练习一步到位)
  • Cherno OpenGL 教程
  • RT-DETRv2 中的坐标回归机制深度解析:为什么用 `sigmoid(inv_sigmoid(ref) + delta)` 而不是除以图像尺寸?
  • OpenCV入门教程
  • 深度学习-计算机视觉-目标检测三大算法-R-CNN、SSD、YOLO
  • 冰火两重天:AI重构下的IT就业图景
  • 从ENIAC到Linux:计算机技术与商业模式的协同演进——云原生重塑闭源主机,eBPF+WebAssembly 双引擎的“Linux 内核即服务”实践
  • 从 MySQL 迁移到 GoldenDB,上来就踩了一个坑。
  • qt界面开发入门以及计算器制作
  • SQL 核心概念与实践总结
  • 【Tourbox】怎么复制预设?
  • RTT操作系统(2)
  • 基于STM32单片机智能手表GSM短信上报GPS定位防丢器设计
  • 力扣658.找到K个最接近的元素
  • LeetCode 面试经典 150_哈希表_赎金信(39_383_C++_简单)
  • LeetCode热题100--114. 二叉树展开为链表--中等
  • 【交易系统系列33】从Raft到Kafka:解构交易所核心系统的一致性与数据持久化之道
  • 数据结构---基于顺序存储结构实现的双端队列
  • C4D建模入门指南:核心术语与高效设置详解
  • Unity核心概念⑧:Input
  • 软考高级-系统架构设计师之指令系统
  • Kafka 运维实战基本操作含命令与最佳实践
  • CAS理解
  • Linux动静态库开发基础:静态库与动态库的编译构建、链接使用及问题排查
  • 深度学习的定义
  • 数据库造神计划第七天---增删改查(CRUD)(3)
  • 【WitSystem】FastAPI目录架构最佳实践