OpenHarmony开发者论坛
标题:
OpenHarmony系统之C++线程异步回调JS机制介绍
[打印本页]
作者:
深开鸿_赵军霞
时间:
2024-4-16 09:15
标题:
OpenHarmony系统之C++线程异步回调JS机制介绍
[md]# OpenHarmony系统之C++线程异步回调JS机制介绍
## 背景介绍
回调函数是 JavaScript 中常见的一种编程模式,它在异步编程中起到了重要作用。在 NAPI (Node.js API)中,回调函数也被广泛应用,用于处理各种异步操作,例如文件读写、网络请求等。按照触发源或目的线程分为JS线程、C++线程,按照回调方式分为同步回调、异步回调,本文重点介绍C++线程异步回调JS的机制。
## C++异步回调JS机制
### 机制一Async Work
首先需要进行数据定义,如下所示
![meth1_1.png](
https://forums-obs.openharmony.c ... 03cuzzsxxcxgpxg.png
"meth1_1.png")
![](./meth1\_1.png)
接着调用napi\_create\_async\_work接口
![meth1_2.png](
https://forums-obs.openharmony.c ... 8hu8yg2emu8cjik.png
"meth1_2.png")
![](./meth1\_2.png)
### 机制二Threadsafe Function
JS函数只能被JS主线程调用。如果 native 创建的其他线程需要调用 JS 函数,则需要拿到 JS 主线程的 napi\_env来调用 N-API 函数。
若native 创建的其他线程必须与 JS 主线程进行通信,线程安全函数API提供了native 创建的其他线程调用 JS 函数的方法。
#### 使用样例
回调函数定义,如下所示
![meth2_1.png](
https://forums-obs.openharmony.c ... c9q1e5yu11hzto5.png
"meth2_1.png")
![](./meth2\_1.png)
应用调用
![meth2_2.png](
https://forums-obs.openharmony.c ... 5hxkakpvhkkf5mj.png
"meth2_2.png")
![](./meth2\_2.png)
#### 使用步骤
线程安全函数的使用步骤是,先 napi\_create\_threadsafe\_function 创建函数引用, napi\_call threadsafe\_function 通过这个函数引用调用线程安全函数。
![meth2_3.png](
https://forums-obs.openharmony.c ... 685hkcbh6xbcf2b.png
"meth2_3.png")
![](./meth2\_3.png)
#### 机制说明
napi create threadsafe\_function 是通过创建 uv \_async 实例 &async 并绑定 AsyncCb, 再在其他线程中调用napi\_call\_threadsafe\_function(tsfn) 后 (tsfn数据结构包含&async),使用 uv\_async\_send(&async) 唤醒持有async的 JS 主线程消息队列,并调用async的回调 AsyncCb->call js\_cb()。
![meth2_4.png](
https://forums-obs.openharmony.c ... 9ffq805b5ffso7f.png
"meth2_4.png")
#### 注意事项
1.napi\_release\_threadsafe\_function 最后一个参数为napi\_tsfn\_abort时,会立即关闭线程安全函数,导致JS主线程无法回调函数;
2.如果创建的线程安全函数的最大队列大小为0,则Napi\_call\_threadsafe\_function()永远不会阻塞。
3.napi\_call\_threadsafe\_function()不应该在JS线程的napi\_tsfn\_blocking中调用,因为如果队列满了,它可能会导致JavaScript线程死锁。
### 机制三uv\_queue\_work
首先需要进行数据定义,如下所示
![meth3_1.png](
https://forums-obs.openharmony.c ... xskhxnunskzs5xx.png
"meth3_1.png")
![](./meth3\_1.png)
接着调用uv\_queue\_work接口
![meth3_2.png](
https://forums-obs.openharmony.c ... i99jaws44nf24if.png
"meth3_2.png")
![](./meth3\_2.png)
## 总结
### 相同点
机制一async\_Work 、机制二Threadsafe Function(简称tsfn)、机制三uv\_queue\_work
使用场景逻辑一致,都是在其他线程主函数运行时,回到 JS 主线程,并将回调函数, push 到 JS 主线程的 event-loop队列里等待被执行。
### 不同点
1.创建的线程不一样: 机制一Napi Async Work 在 queue async work 时会自己创建线程,这个线程属于 Libuv线程池,和 JS主线程一样具有 event-loop 和 napi\_env。机制二tsfn、机制三uv\_queue\_work其他线程处理时开发自己创建新线程,一般根据业务需要创建的,不在Libuv 线程池中,也没有 JS 主线程的特性。
2.JS 主线程的回调函数被执行得到时机、效率不一致:机制一async\_Work 、机制三uv\_queue\_work必须等到新创建的线程主函数被执行完后,被动被执行,只能被调用一次;机制二tsfn的回调函数在其他线程中,可以在任意时机主动调用任意次数,而且不用依赖其他函数。Napi\_Async\_Work 的使用场景是Napi\_Threadsafe\_Function 使用场景的子集,但是 Napi\_Async\_Work 无需开发者创建线程,并且线程具有 event-loop 和 napi\_env 特性。
[/md]
欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/)
Powered by Discuz! X3.5