• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用Node-API接口从异步线程向ArkTS线程投递指定优先级和入队方式的的任务
2<!--Kit: NDK-->
3<!--Subsystem: arkcompiler-->
4<!--Owner: @xliu-huanwei; @shilei123; @huanghello-->
5<!--Designer: @shilei123-->
6<!--Tester: @kirl75; @zsw_zhushiwei-->
7<!--Adviser: @fang-jinxu-->
8Node-API中的napi_call_threadsafe_function_with_priority接口的功能是从异步线程向ArkTS线程投递指定优先级和入队方式的任务,底层队列会根据任务的优先级和入队方式来处理任务。
9
10## 函数说明
11
12```cpp
13napi_status napi_call_threadsafe_function_with_priority(napi_threadsafe_function func, void *data,
14                                                        napi_task_priority priority, bool isTail);
15```
16
17| 参数            | 说明          |
18| :------------- | :----------------------------- |
19| func           | 线程安全方法                   |
20| data           | 异步线程期望传递给主线程的数据  |
21| priority       | 指定任务的优先级[napi_task_priority](napi-data-types-interfaces.md#线程安全任务优先级) |
22| isTail         | 指定任务的入队方式,true代表任务从队列的尾部入队,false代表任务从队列的头部入队 |
23
24## 场景介绍
25异步线程向ArkTS主线程中投递的任务需要根据任务指定的优先级和入队方式进行处理。
26
27## 调用异步的ArkTS接口示例
28
29### 示例代码
30
31- 模块注册
32
33   ```c++
34    // napi_init.cpp
35    #include "napi/native_api.h"
36    #include <string.h>
37    #include <stdlib.h>
38    #include "hilog/log.h"
39
40    static constexpr int INT_NUM_2 = 2;     // int类型数值2
41    static constexpr int INT_NUM_12 = 12;   // int类型数值12
42    static constexpr int INT_NUM_15 = 15;   // int类型数值15
43
44    struct CallbackData {
45        napi_threadsafe_function tsfn;
46        napi_async_work work;
47    };
48    // ArkTS线程的回调实现
49    static void CallJs(napi_env env, napi_value jsCb, void *context, void *data) {
50        if (env == nullptr) {
51            return;
52        }
53        napi_value resultNumber = nullptr;
54        napi_value undefined = nullptr;
55        napi_get_undefined(env, &undefined);
56        napi_value number1 = nullptr;
57        napi_create_int32(env, INT_NUM_12, &number1);
58        napi_value number2 = nullptr;
59        napi_create_int32(env, INT_NUM_15, &number2);
60        napi_value argv[2] = {number1, number2};
61        napi_call_function(env, undefined, jsCb, INT_NUM_2, argv, &resultNumber);
62        int32_t res = 0;
63        // 获取resultNumber对应的int32值
64        napi_get_value_int32(env, resultNumber, &res);
65        OH_LOG_INFO(LOG_APP, "napi_init res is %{public}d", res);
66    }
67
68    // 异步线程中调用该接口向ArkTS线程投递指定优先级和入队方式的任务
69    static void ExecuteWork(napi_env env, void *data) {
70        CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);
71        napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_idle, true); // 投递指定优先级为napi_priority_idle,入队方式为队列尾部入队的任务
72        napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_low, true); // 投递指定优先级为napi_priority_low,入队方式为队列尾部入队的任务
73        napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_high, true); // 投递指定优先级为napi_priority_high,入队方式为队列尾部入队的任务
74        napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_immediate, true); // 投递指定优先级为napi_priority_immediate,入队方式为队列尾部入队的任务
75        napi_call_threadsafe_function_with_priority(callbackData->tsfn, nullptr, napi_priority_high, false); // 投递指定优先级为napi_priority_high,入队方式为队列头部入队的任务
76    }
77
78    static void WorkComplete(napi_env env, napi_status status, void *data) {
79        CallbackData *callbackData = reinterpret_cast<CallbackData *>(data);
80        if (callbackData == nullptr) {
81            return;
82        }
83        napi_release_threadsafe_function(callbackData->tsfn, napi_tsfn_release);
84        napi_delete_async_work(env, callbackData->work);
85        callbackData->work = nullptr;
86        callbackData->tsfn = nullptr;
87        delete callbackData;
88    }
89
90    static napi_value CallThreadSafeWithPriority(napi_env env, napi_callback_info info) {
91        size_t argc = 1;
92        napi_value jsCb = nullptr;
93        CallbackData *callbackData = new CallbackData();
94        napi_get_cb_info(env, info, &argc, &jsCb, nullptr, nullptr);
95        napi_value resourceName = nullptr;
96        napi_create_string_utf8(env, "Thread-safe Function Demo", NAPI_AUTO_LENGTH, &resourceName);
97        napi_create_threadsafe_function(env, jsCb, nullptr, resourceName, 0, 1, nullptr, nullptr, nullptr, CallJs,
98                                        &callbackData->tsfn);
99        // 创建一个异步任务对象
100        napi_create_async_work(env, nullptr, resourceName, ExecuteWork, WorkComplete, callbackData, &callbackData->work);
101        napi_queue_async_work(env, callbackData->work);
102        return nullptr;
103    }
104
105    // 注册模块接口
106    EXTERN_C_START
107    static napi_value Init(napi_env env, napi_value exports)
108    {
109        napi_property_descriptor desc[] = {
110            { "callThreadSafeWithPriority", nullptr, CallThreadSafeWithPriority, nullptr, nullptr, nullptr, napi_default, nullptr }
111        };
112        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
113        return exports;
114    }
115    EXTERN_C_END
116
117    static napi_module nativeModule = {
118        .nm_version = 1,
119        .nm_flags = 0,
120        .nm_filename = nullptr,
121        .nm_register_func = Init,
122        .nm_modname = "entry",
123        .nm_priv = nullptr,
124        .reserved = { 0 },
125    };
126
127    extern "C" __attribute__((constructor)) void RegisterEntryModule()
128    {
129        napi_module_register(&nativeModule);
130    }
131   ```
132   <!-- @[napi_call_threadsafe_function_with_priority_cpp](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIClassicUseCases/NodeAPIApplicationScenario/entry/src/main/cpp/napi_init.cpp) -->
133
134- 接口声明
135
136    ```ts
137    // index.d.ts
138    export const callThreadSafeWithPriority: (cb: (a: number, b: number) => number) => void;
139    ```
140    <!-- @[napi_call_threadsafe_function_with_priority_dts](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIClassicUseCases/NodeAPIApplicationScenario/entry/src/main/cpp/types/libentry/Index.d.ts) -->
141
142- 编译配置
143
144  CMakeLists.txt文件需要按照如下配置
145
146    ```
147    // CMakeLists.txt
148    # the minimum version of CMake.
149    cmake_minimum_required(VERSION 3.4.1)
150    project(myapplication)
151
152    set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
153
154    if(DEFINED PACKAGE_FIND_FILE)
155        include(${PACKAGE_FIND_FILE})
156    endif()
157
158    add_definitions( "-DLOG_TAG=\"LOG_TAG\"" )
159    include_directories(${NATIVERENDER_ROOT_PATH}
160                        ${NATIVERENDER_ROOT_PATH}/include)
161    add_library(entry SHARED napi_init.cpp)
162    target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so)
163    ```
164    <!-- @[napi_call_threadsafe_function_with_priority_cmake](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIClassicUseCases/NodeAPIApplicationScenario/entry/src/main/cpp/CMakeLists.txt) -->
165
166- ArkTS代码示例
167
168    ```ts
169    // index.ets
170    import testNapi from 'libentry.so';
171
172    let callback = (a: number, b: number) : number => {
173        console.info('result is ' + (a + b));
174        return a + b;
175    }
176    testNapi.callThreadSafeWithPriority(callback); // **注意:** 如果底层 ThreadSafeFunction 被取消,则无法保证所有任务都会被执行
177    ```
178    <!-- @[napi_call_threadsafe_function_with_priority_ets](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/NodeAPI/NodeAPIClassicUseCases/NodeAPIApplicationScenario/entry/src/main/ets/pages/Index.ets) -->