NAPI跨线程调用TS线程函数

NAPI跨线程调用TS线程函数

HarmonyOS
2024-05-23 21:43:39
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
fiftystep

一、背景

napi跨线程调用,从ArkTS线程传下来某个函数,在c++子线程调用这个函数。主要使用napi_create_threadsafe_function,napi_create_reference这两个接口。

二、相关接口

NAPI中的线程安全函数

NAPI提供的简便方法,避免了线程间通信,同时可以回到主线程调用JS函数。

napi_create_threadsafe_function:创建线程安全函数,也是一个NAPI对象,包含一个JS函数,可以从多个线程调用。

延长生命周期

从TS层传下来的函数值在对应的作用域才持有他的生命周期,超出作用域需要通过引用的方式延长他的生命周期。

napi_create_reference:为Object创建一个reference,以延长其生命周期。调用者需要自己管理reference生命周期。

三、相关代码

TS侧传入回调函数

Button("跨线程调用JS函数") 
.onClick(() => { 
  entry.threadsTest((value:number) => { 
    value += 10 
    this.cnt += 20 
    hilog.info(0x0000, 'testTag', 'js callback value = ' + value + " , cnt = " + this.cnt); 
    return value 
  }) 
}).margin(10)

处理从TS层传下来的函数

// 从ArkTS侧获取的参数的数量 
size_t argc = 1; 
napi_value js_cb, work_name; 
  
// 获取ArkTS参数 
napi_get_cb_info(env, info, &argc, &js_cb, nullptr, nullptr); 
  
// 指向napi_value js_cb 的 napi_ref cbObj 
napi_create_reference(env, js_cb, 1, &cbObj);

创建线程安全函数

 // 通过UTF8编码的C字符串数据创建work_name 
napi_create_string_utf8(env, "Work Item", NAPI_AUTO_LENGTH, &work_name); 
  
// 创建线程安全函数 
napi_create_threadsafe_function(env, js_cb, NULL, work_name, 0, 1, NULL, NULL, NULL, CallJs, &tsfn);

其他线程中调用线程安全函数

// 其他线程中调用线程安全函数 
std::thread t([]() { 
    // 可获取线程ID 
    std::thread::id this_id = std::this_thread::get_id(); 
    napi_acquire_threadsafe_function(tsfn); 
    napi_call_threadsafe_function(tsfn, NULL, napi_tsfn_blocking); 
}); 
t.detach();

线程安全函数回调函数

static void CallJs(napi_env env, napi_value js_cb, void *context, void *data) 
{ 
// 获取引用值 
napi_get_reference_value(env, cbObj, &js_cb); 
  
// 创建一个ArkTS number作为ArkTS function的入参。 
napi_value argv; 
napi_create_int32(env, cValue, &argv); 
  
napi_value result = nullptr; 
napi_call_function(env, nullptr, js_cb, 1, &argv, &result); 
  
napi_get_value_int32(env, result, &cValue); 
}

四、总结

  • native主线程外的其他线程通常不能直接使用需要napi_env、napi_value的NAPI函数。
  • 线程安全函数可以在其他线程中被调用,并回到主线程中执行。
  • napi_create_threadsafe_function() 创建了一个NAPI对象,该对象包含一个JavaScript函数,并且可以从多个线程调用。
  • 线程安全函数API便提供了一种简化方法,避免了线程间通讯,同时可以回到主线程调用JavaScript函数。
分享
微博
QQ
微信
回复
2024-05-24 17:07:11
相关问题
是否支持Context线程传递
794浏览 • 1回复 待解决
线程线程池的个数限制
352浏览 • 1回复 待解决
如何判断当前线程是否是主线程
1040浏览 • 1回复 待解决
ArkTs多线程方案如何保证线程安全
1126浏览 • 1回复 待解决
TaskPool子线程和主线程如何通信
996浏览 • 1回复 待解决
怎样判断当前线程是否是主线程
51浏览 • 1回复 待解决
线程信息以及线程的任务栈如何获取
669浏览 • 1回复 待解决
zip包的解压是在主线程还是IO线程
651浏览 • 1回复 待解决