napi_threadsafe_function 和 napi_async_work对比分析

前言

从用法和官方介绍角度来看,napi_threadsafe_function 和 napi_async_work 似乎是两个完全不相同的两个东西,但从源码分析他们实现的原理,是有很大重合度。以至于使用场景亦有重合的地方。

读前须知

  • uv_async_send、uv_async_init、uv_queue_work 具体用法和作用。
  • napi_async_work 系列 API 具体用法和作用。
  • 线程安全函数 API 具体用法和作用。
  • Libuv 线程池里的线程都有 napi env 环境和都持有一个 event-loop。
  • JS 主线程是 Libuv 线程池中某一个线程,napi_queue_async_work 创建的线程也在 Libuv 线程池里。

napi_async_work

napi_async_work 解决了什么问题?

对于耗时的操作。如果在 Libuv 的主线程里执行的话, 就会阻塞后面的任务执行。所以 Libuv 里维护了一个线程池。简单的说,napi_async_work 负责创建一个新线程放入 Libuv 线程池,去执行耗时操作,待线程执行结束,将回调函数 push 到主线程的 eventloop 内等待被执行。

源码分析 (请下载 node.js 源码,并且结合源码阅读)

使用 napi_create_async_work 创建异步 work;源码中实例化了 uvimpl::Work,把实例引用地址赋值给 result。

napi_create_async_work(napi_env env,
                       napi_value async_resource,
                       napi_value async_resource_name,
                       napi_async_execute_callback execute,
                       napi_async_complete_callback complete,
                       void* data,
                       napi_async_work* result) {
  uvimpl::Work* work = uvimpl::Work::New(reinterpret_cast<node_napi_env>(env),
                                         resource,
                                         resource_name,
                                         execute,
                                         complete,
                                         data);

  *result = reinterpret_cast<napi_async_work>(work);

  return napi_clear_last_error(env);
}

uvimpl::Work 实际上继承了 ThreadPoolWork,所以说上面的实例是 ThreadPoolWork 实例

class Work : public node::AsyncResource, public node::ThreadPoolWork {
 private:
  explicit Work(node_napi_env env,
                v8::Local<v8::Object> async_resource,
                v8::Local<v8::String> async_resource_name,
                napi_async_execute_callback execute,
                napi_async_complete_callback complete = nullptr,
                void* data = nullptr)
      : AsyncResource(
<think>好的,我现在需要回答用户关于鸿蒙操作系统中子线程的使用方法实现机制的问题。首先,我得仔细阅读用户提供的参考资料,也就是引用[1]到[4],确保理解里面的内容。用户特别提到了C++子线程与UI主线程的通信方案,所以重点应该放在线程间通信上,尤其是如何在Native子线程ArkTS主线程之间安全地传递消息。 首先,我需要整理一下参考资料中的关键点。引用[2][3]提到了使用Node-API中的napi_threadsafe_function来实现线程安全函数,允许子线程与主线程异步通信。引用[3][4]详细描述了实现流程,包括创建线程安全函数、使用异步工作(napi_create_async_work)、处理业务逻辑资源清理等步骤。这些都是需要涵盖的重点内容。 接下来,我需要按照用户的要求,结构清晰地分步骤解释鸿蒙子线程的用法实现机制。可能需要分为几个部分:线程基础概念、子线程创建、通信机制、实现流程、注意事项等。同时,用户要求回答中使用中文,并且数学表达式用$...$格式,独立公式用$$...$$,不过在这个问题中可能数学公式较少,但需要注意代码块的格式是否正确。 然后,我需要确保回答中的技术细节准确无误,例如正确引用napi_threadsafe_function相关API的使用步骤。同时,根据用户提供的示例,可能需要生成相关问题,所以得在最后添加几个相关问题,帮助用户进一步学习。 需要注意的是,用户引用的资料中有关于Node-API的使用,特别是线程安全函数异步任务的实现流程。这部分需要详细解释,包括如何注册回调、处理异步任务以及资源回收。同时,要强调ArkTS主线程不能直接被子线程访问,必须通过安全机制进行通信。 在组织内容时,应该先介绍子线程的基本概念必要性,然后说明在鸿蒙中如何创建子线程,接着详细讲解通信机制,包括使用的API具体步骤。最后提到注意事项,比如避免阻塞主线程、资源管理等。 需要检查是否有遗漏的关键点,比如napi_create_async_work的作用,ExecuteWorkWorkComplete的具体功能,以及如何通过callback回到主线程调用ArkTS函数。这些都是用户资料中的重点,必须涵盖到。 最后,生成的相关问题需要围绕线程管理、通信优化、与其他系统的对比等方向,帮助用户深入理解。例如,如何确保线程安全、优化通信性能、处理线程间数据共享等。</think>### 鸿蒙操作系统中子线程的使用方法与实现机制 #### 1. 子线程基础概念 在鸿蒙(HarmonyOS)中,UI主线程负责处理用户交互界面渲染,而子线程用于执行耗时操作(如网络请求、文件读写、复杂计算等),避免阻塞主线程[^2]。**子线程不能直接操作UI资源**,需通过线程安全机制与主线程通信。 --- #### 2. 子线程的创建与使用 **C++层子线程创建示例**: ```cpp #include <thread> void NativeThreadTask() { // 子线程中的业务逻辑 } // 创建并启动子线程 std::thread worker(NativeThreadTask); worker.detach(); // 分离线程,避免资源泄漏 ``` - **注意**:需在`CMakeLists.txt`中添加`libc++_shared.so`依赖以支持C++多线程。 --- #### 3. 子线程与主线程通信机制 鸿蒙通过**Node-API的线程安全函数(napi_threadsafe_function)**实现跨线程通信,核心流程如下: ##### 3.1 核心API与流程 1. **创建线程安全函数** ```cpp napi_create_threadsafe_function( env, func, // ArkTS回调函数 async_resource, async_resource_name, max_queue_size, initial_thread_count, finalize_cb, context, &threadsafe_func ); ``` 2. **注册异步任务** 使用`napi_create_async_work`定义异步任务的执行完成回调: ```cpp napi_create_async_work( env, nullptr, resource_name, ExecuteWork, // 子线程中执行 WorkComplete, // 主线程中完成清理 &async_data, &async_work ); ``` 3. **通信过程** - **子线程处理**:在`ExecuteWork`中执行业务逻辑,通过`napi_call_threadsafe_function`触发线程安全函数。 - **主线程回调**:线程安全函数将任务封装后,通过`napi_call_function`调用ArkTS侧注册的callback[^3]。 --- #### 4. 实现流程详解 1. **ArkTS侧定义异步任务** ```typescript nativeModule.runAsyncTask((result: string) => { console.log("Result from C++ thread: " + result); }); ``` 2. **Native侧绑定线程安全函数** - 将ArkTS的`callback`绑定到线程安全函数。 - 通过`napi_acquire_threadsafe_function`获取函数句柄。 3. **子线程触发通信** ```cpp napi_call_threadsafe_function( threadsafe_func, data, napi_tsfn_blocking ); ``` 4. **资源清理** 在`WorkComplete`中使用`napi_release_threadsafe_function`释放资源[^4]。 --- #### 5. 注意事项 1. **线程安全**:避免直接操作主线程资源,所有跨线程数据需通过安全接口传递。 2. **性能优化**:控制子线程数量,避免过度竞争;使用`non-blocking`模式减少延迟。 3. **生命周期管理**:确保子线程在组件销毁时终止,防止内存泄漏。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值