基于libuv异步库进行线程通信?

应用内核里面会开很多子线程,执行一些耗时操作,逐层传递env的异步任务方式太过繁琐,影响性能体验,通过libuv库可以很好的避免这种问题。

阅读 4k
1 个回答

1.从ArkTS层注册UI层的处理函数到C++层,该处理函数为UI的刷新处理函数,C++层收到该注册处理后,存储env信息与处理函数为全局变量。

2.C++层建立的大量子线程,其各子线程的处理函数中业务处理完毕后,通过调用libuv接口(如uv_queue_work)抛ArkTS任务到loop中执行。

3.在uv_queue_work中组装信息,返回给第一步中注册的函数来作UI刷新。

具体方法可参考示例代码:

1.ArkTS侧传递UI处理函数。

// index.ets 
import { hilog } from '@kit.PerformanceAnalysisKit'; 
import testNapi from 'libentry.so'; 
... 
.onClick(() => { 
  testNapi.regArkts((result: number) => { 
    hilog.info(0x0000, 'testTag', 'Pure regArkts %{public}d', result); 
    this.message = 'result is' + result.toString(); 
  }) 
}) 
 
// index.d.ts 
export const regArkts: (c: (a: number) => void) => number;

2.native侧注册处理并抛ArkTS任务到loop中执行。

#include "napi/native_api.h" 
#include "hilog/log.h" 
#include <thread> 
#include <unistd.h> 
#include <uv.h> 
#undef LOG_DOMAIN 
#undef LOG_TAG 
#define LOG_DOMAIN 0x3200 // 全局domain宏,标识业务领域 
#define LOG_TAG "MY_TAG"  // 全局tag宏,标识模块日志tag 
 
struct CallbackContext { 
    napi_env env = nullptr; 
    napi_ref callbackRef = nullptr; 
    int retData = 0; 
}; 
void CallbackTest(CallbackContext *context) { 
    std::thread::id this_id3 = std::this_thread::get_id(); 
    OH_LOG_INFO(LOG_APP, "thread id3 %{public}lu.\n", pthread_self()); 
    uv_loop_s *loop = nullptr; 
    // 此处的env需要在注册Arkts回调时保存下来。从env中获取对应的Arkts线程的loop。 
    napi_get_uv_event_loop(context->env, &loop); 
    // 创建uv_work_t用于传递私有数据,注意回调完成后需要释放内存,此处省略生成回传数据的逻辑,传回int类型1。 
    uv_work_t *work = new uv_work_t; 
    context->retData = 1; 
    work->data = (void *)context; 
    // 调用libuv接口抛ArkTS任务到loop中执行。 
    uv_queue_work( 
        loop, work, 
        // 此回调在另一个普通线程中执行,用于处理异步任务,回调执行完后执行下面的回调。本场景下该回调不需要执行任务。 
        [](uv_work_t *work) {}, 
        // 此回调会在env对应的ArkTS线程中执行。 
        [](uv_work_t *work, int status) { 
            CallbackContext *context = (CallbackContext *)work->data; 
            napi_handle_scope scope = nullptr; 
            // 打开handle_scope用于管理napi_value的生命周期,否则会内存泄露。 
            napi_open_handle_scope(context->env, &scope); 
            if (scope == nullptr) { 
                return; 
            } 
            napi_value callback = nullptr; 
            napi_get_reference_value(context->env, context->callbackRef, &callback); 
            napi_value retArg; 
            napi_create_int32(context->env, context->retData, &retArg); 
            napi_value ret; 
            napi_call_function(context->env, nullptr, callback, 1, &retArg, &ret); 
            napi_delete_reference(context->env, context->callbackRef); 
            // 关闭handle_scope释放napi_value。 
            napi_close_handle_scope(context->env, scope); 
            std::thread::id this_id4 = std::this_thread::get_id(); 
            OH_LOG_INFO(LOG_APP, "thread id4 %{public}lu.\n", pthread_self()); 
            // 释放work指针。 
            if (work != nullptr) { 
                delete work; 
            } 
            delete context; 
        }); 
} 
static napi_value RegArkts(napi_env env, napi_callback_info info) { 
    std::thread::id this_id1 = std::this_thread::get_id(); 
    OH_LOG_INFO(LOG_APP, "thread id1 %{public}lu.\n", pthread_self()); 
    size_t argc = 1; 
    napi_value argv[1] = {0}; 
    napi_value thisVar = nullptr; 
    void *data = nullptr; 
    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 
    napi_valuetype valueType = napi_undefined; 
    napi_typeof(env, argv[0], &valueType); 
    if (valueType != napi_function) { 
        return nullptr; 
    } 
    auto g_CallbackContext = new CallbackContext(); 
    g_CallbackContext->env = env; 
    napi_create_reference(env, argv[0], 1, &g_CallbackContext->callbackRef); 
    std::thread testThread(CallbackTest, g_CallbackContext); 
    testThread.detach(); 
    std::thread::id this_id2 = std::this_thread::get_id(); 
    OH_LOG_INFO(LOG_APP, "thread id2 %{public}lu.\n", pthread_self()); 
    return thisVar; 
} 
 
EXTERN_C_START 
static napi_value Init(napi_env env, napi_value exports) { 
    napi_property_descriptor desc[] = { 
        {"regArkts", nullptr, RegArkts, nullptr, nullptr, nullptr, napi_default, nullptr}}; 
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 
    return exports; 
} 
EXTERN_C_END 
... 
 
// CMakeLists.txt 链接libuv库 
target_link_libraries(entry PUBLIC libace_napi.z.so libuv.so libhilog_ndk.z.so)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进