diff --git a/zh-cn/application-dev/arkts-utils/arkts-sendable.md b/zh-cn/application-dev/arkts-utils/arkts-sendable.md index d1f59429a0e91a92ef533d4559db50449d33fb13..b9c8012b73487e40458f5dad7bdfe10819d79caf 100644 --- a/zh-cn/application-dev/arkts-utils/arkts-sendable.md +++ b/zh-cn/application-dev/arkts-utils/arkts-sendable.md @@ -1,17 +1,17 @@ # Sendable对象简介 -在传统JS引擎中,优化对象的并发通信开销的唯一方法是将实现下沉到Native侧,通过[Transferable对象](transferabled-object.md)的转移或共享来降低并发通信开销。但开发者仍有大量对象并发通信的需求,这个问题在业界JS引擎中未得到解决。 +在传统JS引擎中,要优化对象的并发通信开销,唯一的方法是将实现下沉到Native侧,通过[Transferable对象](transferabled-object.md)的转移或共享来降低开销。然而,开发者仍有大量对象并发通信的需求,这个问题在业界JS引擎中尚未解决。 ArkTS提供了Sendable对象类型,在并发通信时支持通过引用传递来解决上述问题。 -Sendable对象为可共享的,其跨线程前后指向同一个JS对象。如果包含JS或Native内容,可以直接共享。如果底层是Native实现,则需要考虑线程安全性。通信过程如下图所示: +Sendable对象可共享,跨线程前后指向同一个JS对象。如果包含JS或Native内容,可以直接共享。如果底层是Native实现,则需要确保线程安全性。通信过程如下图所示: ![sendable](figures/sendable.png) 与其它ArkTS数据对象不同,符合Sendable协议的数据对象在运行时应为类型固定的对象。 -当多个并发实例尝试同时更新Sendable数据时,会发生数据竞争,例如[ArkTS共享容器](arkts-collections-introduction.md)的多线程操作。因此,ArkTS提供[异步锁](arkts-async-lock-introduction.md)机制来避免不同并发实例间的数据竞争,并提供了[异步等待](arkts-condition-variable-introduction.md)机制来控制多线程处理数据的时序。同时,还可以通过[对象冻结接口](sendable-freeze.md)将对象冻结为只读,从而避免数据竞争问题。 +当多个并发实例尝试同时更新Sendable数据时,会发生数据竞争,例如[ArkTS共享容器](arkts-collections-introduction.md)的多线程操作。因此,ArkTS提供[异步锁](arkts-async-lock-introduction.md)机制来避免不同并发实例间的数据竞争,并提供了[异步等待](arkts-condition-variable-introduction.md)机制来控制多线程处理数据的时序。同时,还可以通过[对象冻结接口](sendable-freeze.md)将对象冻结为只读,从而避免数据竞争。 Sendable对象提供了并发实例间高效的通信能力,即引用传递,适用于开发者自定义大对象需要线程间通信的场景,例如子线程读取数据库数据并返回给宿主线程,具体代码实现可参考[跨并发实例传输大数据场景](sendable-guide.md#跨并发实例传输大数据场景)。 ## 基础概念 @@ -20,7 +20,7 @@ Sendable对象提供了并发实例间高效的通信能力,即引用传递, Sendable协议定义了ArkTS的可共享对象体系及其规格约束。符合Sendable协议的数据(以下简称Sendable对象)可以在ArkTS并发实例间传递。 -默认情况下,Sendable数据在ArkTS并发实例间(包括UI主线程、TaskPool线程、Worker线程)传递的行为是引用传递。同时,ArkTS也支持Sendable数据在这些实例间拷贝传递。 +默认情况下,Sendable数据在ArkTS并发实例间(包括UI主线程、TaskPool线程、Worker线程)传递时采用引用传递。ArkTS还支持在这些实例间对Sendable数据进行拷贝传递。 ### ISendable @@ -46,13 +46,13 @@ Sendable class需同时满足以下两个规则: > > - 针对API version 12的工程,开发者使用\@Sendable装饰器校验Sendable function时,需在工程中配置"compatibleSdkVersionStage": "beta3",否则其Sendable特性将不生效。参考[build-profile.json5配置文件说明](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-hvigor-build-profile-V5)。 > -> - 针对API version大于12的工程,开发者可直接使用\@Sendable装饰器校验Sendable function,无需再进行其他配置。 +> - 针对API version大于12的工程,可直接使用\@Sendable装饰器校验Sendable function,无需再进行其他配置。 Sendable function需同时满足以下两个规则: 1. 当且仅当被标注了[@Sendable装饰器](#sendable装饰器)。 -2. 需满足Sendable约束,详情可查[Sendable使用规则](sendable-constraints.md)。 +2. 需满足Sendable约束,具体可参考[Sendable使用规则](sendable-constraints.md)。 ### Sendable interface @@ -60,7 +60,7 @@ Sendable interface需同时满足以下两个规则: 1. 当且仅当是[ISendable](#isendable)或者继承了ISendable。 -2. 需满足Sendable约束,详情可查[Sendable使用规则](sendable-constraints.md)。 +2. 需满足Sendable约束,具体可参考[Sendable使用规则](sendable-constraints.md)。 ### Sendable支持的数据类型 @@ -78,7 +78,7 @@ Sendable interface需同时满足以下两个规则: - 标注了[@Sendable装饰器](#sendable装饰器)的function。 -- 接入Sendable的系统对象。 +- 接入Sendable的系统对象: - [共享用户首选项](../reference/apis-arkdata/js-apis-data-sendablePreferences.md) - [可共享的色彩管理](../reference/apis-arkgraphics2d/js-apis-sendableColorSpaceManager.md) - [基于Sendable对象的图片处理](../reference/apis-image-kit/js-apis-sendableImage.md) @@ -87,43 +87,43 @@ Sendable interface需同时满足以下两个规则: - 元素均为Sendable类型的union type数据。 -- 开发者自定义的Native Sendable对象。详情可参考[自定义Native Sendable对象的多线程操作场景](napi-define-sendable-object.md)。 +- 开发者可自定义Native Sendable对象。详情参见[自定义Native Sendable对象的多线程操作场景](napi-define-sendable-object.md)。 > **说明:** > -> - JS内置对象在并发实例间的传递遵循结构化克隆算法,跨线程行为是拷贝传递。因此,JS内置对象的实例不是Sendable类型。 +> - JS内置对象在并发实例间传递时遵循结构化克隆算法,跨线程行为是拷贝传递。因此,JS内置对象的实例不是Sendable类型。 > -> - 对象字面量、数组字面量在并发实例间的传递遵循结构化克隆算法,跨线程行为是拷贝传递。因此,对象字面量和数组字面量不是Sendable类型。 +> - 对象字面量和数组字面量在并发实例间传递时遵循结构化克隆算法,跨线程行为是拷贝传递。因此,对象字面量和数组字面量不是Sendable类型。 ## Sendable的实现原理 -为了实现[Sendable数据](#sendable支持的数据类型)在不同并发实例间的引用传递,Sendable共享对象分配在共享堆中,实现跨并发实例的内存共享。 +为了实现[Sendable数据](#sendable支持的数据类型)在不同并发实例间的引用传递,将Sendable共享对象分配在共享堆中,实现跨并发实例的内存共享。 -共享堆(SharedHeap)是进程级别的堆空间,与虚拟机本地堆(LocalHeap)不同的是,LocalHeap只能被单个并发实例访问,而SharedHeap可以被所有线程访问。一个Sendable对象的跨线程行为是引用传递。因此,一个Sendable对象可能被多个并发实例引用,判断该Sendable对象是否存活,取决于所有并发实例是否存在对此Sendable对象的引用。 +共享堆(SharedHeap)是进程级别的堆空间,与虚拟机本地堆(LocalHeap)不同,LocalHeap仅限单个并发实例访问,而SharedHeap可被所有线程访问。Sendable对象的跨线程行为为引用传递,因此,一个Sendable对象可能被多个并发实例引用。判断该Sendable对象是否存活,取决于所有并发实例是否存在对此Sendable对象的引用。 **SharedHeap与LocalHeap关系图** ![zh-cn_image_0000002001521153](figures/zh-cn_image_0000002001521153.png) -各个并发实例的LocalHeap是隔离的,SharedHeap是进程级别的堆,可以被所有并发实例引用,但SharedHeap不能引用LocalHeap中的对象。 +各个并发实例的LocalHeap是隔离的。SharedHeap是进程级别的堆,可以被所有并发实例引用,但SharedHeap不能引用LocalHeap中的对象。 ## \@Sendable装饰器 -声明并校验Sendable class以及Sendable function。 +声明并校验Sendable class和Sendable function。 | \@Sendable装饰器 | 说明 | | -------- | -------- | | 装饰器参数 | 无。 | | 使用场景限制 | 仅支持在Stage模型的.ets文件中使用。 | | 装饰的函数类型限制 | 仅支持装饰普通function和Async function类型。 | -| 装饰的类继承关系限制 | Sendable class只能继承Sendable class,普通Class不可以继承Sendable class。 | +| 装饰的类继承关系限制 | Sendable class只能继承Sendable class,普通Class不可继承Sendable class。 | | 装饰的对象内的属性类型限制 | 1. 支持string、number、boolean、bigint、null、undefined、Sendable class、collections容器集、ArkTSUtils.locks.AsyncLock、ArkTSUtils.SendableLruCache以及自定义的Sendable函数类型。
2. 禁止使用闭包变量,定义在顶层的Sendable class和Sendable function除外。
3. 不支持通过\#定义私有属性,需用private。
4. 不支持计算属性。 | | 装饰的对象内的属性的其他限制 | 1. 成员属性必须显式初始化,不能使用感叹号。
2. 不支持增加或删除属性,允许修改属性,修改前后属性的类型必须一致,不支持修改方法。| -| 装饰的函数或类对象内的方法参数限制 | 允许使用local变量、入参和通过import引入的变量。禁止使用闭包变量,定义在顶层的Sendable class和Sendable function除外。从API version 18开始,支持访问本文件导出的变量。 | -| 适用场景 | 1. 在TaskPool或Worker中使用类方法/Sendable函数。
2. 传输对象数据量较大的使用场景。序列化耗时会随着数据量增大而增大,使用Sendable对数据改造后传输100KB数据时效率提升约20倍,传输1M数据时效率提升约100倍。 | +| 装饰的函数或类对象内的方法参数限制 | 允许使用local变量、入参和通过import引入的变量。禁止使用闭包变量,但定义在顶层的Sendable class和Sendable function除外。从API version 18开始,支持访问本文件导出的变量。 | +| 适用场景 | 1. 在TaskPool或Worker中使用类方法或Sendable函数。
2. 传输对象数据量较大的使用场景。序列化耗时会随着数据量增大而增大,使用Sendable对数据进行改造后,传输100KB数据时效率提升约20倍,传输1M数据时效率提升约100倍。 | **装饰器修饰Class使用示例:** diff --git a/zh-cn/application-dev/arkts-utils/arraybuffer-object.md b/zh-cn/application-dev/arkts-utils/arraybuffer-object.md index 727f11f8b480e724b3ff41ca41241f9be5d09318..4f3fa10c03f6afc54ee50c6d5672442e3c1f0614 100644 --- a/zh-cn/application-dev/arkts-utils/arraybuffer-object.md +++ b/zh-cn/application-dev/arkts-utils/arraybuffer-object.md @@ -1,28 +1,28 @@ # ArrayBuffer对象 -ArrayBuffer由两部分组成:底层存储数据的Native内存区域,以及封装操作的JS对象壳,该JS对象壳被分配在虚拟机本地堆(LocalHeap)。跨线程传递时,JS对象壳需要经过序列化与反序列化拷贝传递,Native内存区域则有两种传递方式:拷贝和转移。 +ArrayBuffer包含两部分:底层存储数据的Native内存区域,以及封装操作的JS对象壳。JS对象壳分配在虚拟机的本地堆(LocalHeap)中。跨线程传递时,JS对象壳需要序列化和反序列化拷贝传递,而Native内存区域可以通过拷贝或转移的方式传递。 -Native内存采用拷贝方式(递归遍历),传输后两个线程可以独立访问ArrayBuffer。这种传输方式不仅需要重建JS壳,还需要拷贝Native内存,传输效率较低。通信过程如下图所示: +Native内存通过拷贝方式(递归遍历),传输后两个线程可以独立访问ArrayBuffer。此方式需要重建JS壳和拷贝Native内存,传输效率较低。通信过程如下图所示: ![copy_transfer](figures/copy_transfer.png) -Native内存采用转移方式,传输后原线程将无法使用此ArrayBuffer对象。跨线程时只需重建JS壳,Native内存无需拷贝,效率更高。通信过程如下图所示: +Native内存通过转移方式传输,传输后原线程将无法使用此ArrayBuffer对象。跨线程时只需重建JS壳,Native内存无需拷贝,从而提高效率。通信过程如下图所示: ![transfer](figures/transfer.png) -ArrayBuffer可以用来表示图片等资源,在应用开发中,处理图片(如调整亮度、饱和度、大小等)往往比较耗时,为了避免长时间阻塞UI主线程,可以将图片传递到子线程中进行处理。采用转移方式传递ArrayBuffer传输性能更高,但原线程无法再访问ArrayBuffer对象。如果两个线程都需要访问该对象,只能采用拷贝方式。反之,建议采用转移方式,以获得更高的传输效率,从而提升性能。 +ArrayBuffer可以用来表示图片等资源,在应用开发中,处理图片(如调整亮度、饱和度、大小等)会比较耗时,为了避免长时间阻塞UI主线程,可以将图片传递到子线程中进行处理。采用转移方式传递ArrayBuffer可提高传输性能,但原线程将无法再访问该ArrayBuffer对象。如果两个线程都需要访问该对象,只能采用拷贝方式。反之,建议采用转移方式以提升性能。 -以下将通过案例分别介绍拷贝和转移两种方式,实现图片跨ArkTS线程传输。 +以下将通过具体的代码案例分别介绍拷贝和转移两种方式,实现图片跨ArkTS线程传输。 ## ArrayBuffer拷贝传输方式 -在ArkTS中,TaskPool传递ArrayBuffer数据时,默认使用转移方式,通过调用setTransferList()接口,可以指定部分数据的传递方式为转移方式,而其他部分数据可以切换为拷贝方式。 +在ArkTS中,TaskPool传递ArrayBuffer数据时,默认采用转移方式。通过调用setTransferList()接口,可以指定部分数据的传递方式为转移方式,其他部分数据可以切换为拷贝方式。 首先,实现一个处理ArrayBuffer的接口,该接口在Task中执行。 -然后,通过拷贝方式将ArrayBuffer数据传递到Task中,并处理。 +然后,通过拷贝方式将ArrayBuffer数据传递到Task中,并进行处理。 -最后,UI主线程接收到Task执行完毕后返回的ArrayBuffer数据,拼接并展示。 +最后,UI主线程接收到Task执行完毕后返回的ArrayBuffer数据,进行拼接并展示。 ```ts // Index.ets @@ -86,4 +86,4 @@ struct Index { ## ArrayBuffer转移传输方式 -在TaskPool中,传递ArrayBuffer数据时默认使用转移方式,原线程将无法再使用已传输给子线程的ArrayBuffer。在上文示例的基础上去除task.setTransferList接口调用,即在createImageTask的第二个参数传入true,就可以实现转移方式的传输。 +在TaskPool中,传递ArrayBuffer数据时,默认使用转移方式,原线程将无法再使用已传输给子线程的ArrayBuffer。 在上文示例的基础上去除task.setTransferList接口调用,即在createImageTask的第二个参数传入true,就可以实现转移方式的传输。 diff --git a/zh-cn/application-dev/arkts-utils/async-concurrency-overview.md b/zh-cn/application-dev/arkts-utils/async-concurrency-overview.md index 2879330084d4d4bcb0fa3f4d14c6a1912ddfc1a2..0a2f8f8b8078d5a1522a4ff33725f70117548813 100644 --- a/zh-cn/application-dev/arkts-utils/async-concurrency-overview.md +++ b/zh-cn/application-dev/arkts-utils/async-concurrency-overview.md @@ -1,23 +1,23 @@ # 异步并发 (Promise和async/await) -Promise和async/await提供异步并发能力,是标准的JS异步语法。异步代码会被挂起并在之后继续执行,同一时间只有一段代码执行。以下是典型的异步并发使用场景: +Promise和async/await是标准的JS异步语法,提供异步并发能力。异步代码执行时会被挂起,稍后继续执行,确保同一时间只有一段代码在运行。以下是典型的异步并发使用场景: -- I/O 非阻塞操作​​:网络请求、文件读写、定时器等。 +- I/O 非阻塞操作:网络请求、文件读写、定时器等。 -- 任务轻量且无 CPU 阻塞​​:单次任务执行时间短。 +- 任务轻量且无 CPU 阻塞:单次任务执行时间短。 -- 逻辑依赖清晰​​:任务有明确的顺序或并行关系。 +- 逻辑依赖清晰:任务有明确的顺序或并行关系。 -异步并发是一种编程语言的特性,允许程序在执行某些操作时不必等待其完成,可以继续执行其他操作。 +异步并发是一种编程语言的特性,允许程序在执行某些操作时不必等待其完成,可以继续执行其他异步代码。 ## Promise -Promise是一种用于处理异步操作的对象,可以将异步操作转换为类似于同步操作的风格,以方便代码编写和维护。Promise提供了一种状态机制来管理异步操作的不同阶段,Promise有三种状态:pending(进行中)、fulfilled(已完成,也叫resolved)和rejected(已拒绝)。其创建后处于pending状态,异步操作完成后转换为fulfilled或rejected状态。 +Promise是一种用于处理异步操作的对象,可将异步操作转换为类似同步操作的风格,便于代码编写和维护。Promise通过状态机制管理异步操作的不同阶段,有三种状态:pending(进行中)、fulfilled(已完成,也叫resolved)和rejected(已拒绝)。创建后处于pending状态,异步操作完成后转换为fulfilled或rejected状态。 -Promise提供了then/catch方法来注册回调函数以处理异步操作的成功或失败的结果,Promise状态改变会触发回调函数加入微任务队列等待执行,依赖事件循环机制在宏任务执行完成后优先执行微任务,保证回调函数的异步调度。 +Promise提供了then/catch方法来注册回调函数,以处理异步操作的成功或失败结果。当Promise状态改变时,回调函数会被加入微任务队列等待执行,依赖事件循环机制在宏任务执行完成后优先执行微任务,从而保证回调函数的异步调度。 -最基本的用法是通过构造函数实例化一个Promise对象,同时传入一个带有两个参数的函数,通常称为executor函数。executor函数接收两个参数:resolve和reject,分别表示异步操作成功和失败时的回调函数。例如,以下代码创建了一个Promise对象并模拟了一个异步操作: +最基本的用法是通过构造函数实例化一个Promise对象,传入一个带有两个参数的函数,称为executor函数。executor函数接收两个参数:resolve和reject,分别表示异步操作成功和失败时的回调函数。 ```ts const promise: Promise = new Promise((resolve: Function, reject: Function) => { @@ -57,7 +57,7 @@ promise.then((result: number) => { ``` -在上述代码中,then方法的回调函数接收Promise对象的成功结果作为参数,并输出到控制台。如果Promise对象进入rejected状态,catch方法的回调函数接收错误对象作为参数,并输出到控制台。 +在上述代码中,then方法的回调函数接收Promise对象的成功结果,并输出到控制台。如果Promise对象进入rejected状态,catch方法的回调函数接收错误对象,并输出到控制台。 > **说明:** > @@ -65,11 +65,11 @@ promise.then((result: number) => { ## async/await -async/await是一种用于处理异步操作的Promise语法糖,使得编写异步代码变得更加简单和易读。通过使用async关键字声明一个函数为异步函数,并使用await关键字等待Promise的解析(完成或拒绝),以同步的方式编写异步操作的代码。 +async/await是用于处理异步操作的Promise语法糖,使编写异步代码更加简单和易读。使用async关键字声明异步函数,并使用await关键字等待Promise的解析(完成或拒绝),以同步方式编写异步操作的代码。 -async函数通过返回Promise对象实现异步操作,其内部可以包含零个或者多个await关键字,通过await暂停执行直至关联的Promise完成状态转换(fulfilled/rejected)。若函数执行过程中抛出异常,该异常将直接触发返回的Promise进入rejected状态,错误对象可通过.catch()方法或then的第二个回调参数捕获。 +async函数返回Promise对象,实现异步操作。函数内部可包含零个或多个await关键字,await会暂停执行,直到关联的Promise完成状态转换(fulfilled或rejected)。若函数执行过程中抛出异常,该异常将直接触发返回的Promise进入rejected状态,错误对象可通过.catch()方法或then的第二个回调参数捕获。 -下面是一个使用async/await的例子,其中模拟了一个以同步方式执行异步操作的场景,该操作会在3秒钟后返回一个字符串。 +下面是一个使用async/await的示例,模拟同步方法执行异步操作的场景,3秒后返回一个字符串。 ```ts async function myAsyncFunction(): Promise { @@ -105,9 +105,9 @@ struct Index { ``` -在上述示例代码中,使用了await关键字来等待Promise对象的解析,并将其解析值存储在result变量中。 +在上述示例代码中,使用await等待Promise解析,并存储在result变量中。 -需要注意的是,等待异步操作时,需将整个操作包在async函数中,并搭配await使用,同时也可使用try/catch块来捕获异步操作中的异常。 +需要注意的是,等待异步操作时,需将操作包在async函数中,并搭配await使用。同时也可使用try/catch块来捕获异常。 ```ts async function myAsyncFunction(): Promise { diff --git a/zh-cn/application-dev/arkts-utils/concurrency-overview.md b/zh-cn/application-dev/arkts-utils/concurrency-overview.md index f243b8d73829935f01b1abfdea0c202ad162d559..cbea0b255adca34374de069b620ea37675b0278b 100644 --- a/zh-cn/application-dev/arkts-utils/concurrency-overview.md +++ b/zh-cn/application-dev/arkts-utils/concurrency-overview.md @@ -1,14 +1,14 @@ # 并发概述 -并发是指在同一时间内,存在多个任务同时执行的情况。对于多核设备,这些任务可以在不同CPU上并行执行。对于单核设备,尽管多个并发任务不会在同一时刻并行执行,但CPU会在某个任务休眠或进行I/O操作时切换任务,调度执行其他任务,从而提高CPU的资源利用率。 +并发指在同一时间内,多个任务同时执行。在多核设备上,任务可以在不同CPU上并行执行。对于单核设备,尽管多个任务不会同时并行,但CPU会在某个任务休眠或进行I/O操作时切换任务,调度其他任务,提高CPU的资源利用率。 -为了提升应用的响应速度与帧率,避免耗时任务影响UI主线程,ArkTS提供了异步并发和多线程并发两种处理策略。 +为了提升应用的响应速度和帧率,避免耗时任务影响UI主线程,ArkTS提供了异步并发和多线程并发两种处理策略。 -- 异步并发是指异步代码在执行到一定程度后会被暂停,以便在未来某个时间点继续执行,这种情况下,同一时间只有一段代码在执行。ArkTS通过Promise和async/await提供异步并发能力,适用于单次I/O任务的开发场景。详细请参见[使用异步并发能力](async-concurrency-overview.md)。 +- 异步并发是指异步代码在执行到一定程度后暂停,并在未来某个时间点继续执行,同一时间只有一段代码执行。ArkTS通过Promise和async/await提供异步并发能力,适用于单次I/O任务。详细请参见[使用异步并发能力](async-concurrency-overview.md)。 -- 多线程并发允许在同一时间段内同时执行多段代码。在UI主线程继续响应用户操作和更新UI的同时,后台线程也能执行耗时操作,从而避免应用出现卡顿。ArkTS通过TaskPool和Worker提供多线程并发能力,适用于[耗时任务](time-consuming-task-overview.md)等并发场景。详细请参见[多线程并发概述](multi-thread-concurrency-overview.md)。 +- 多线程并发允许同时执行多段代码。UI主线程继续响应用户操作和更新UI,后台线程执行耗时操作,避免应用卡顿。ArkTS通过TaskPool和Worker提供多线程并发能力,适用于[耗时任务](time-consuming-task-overview.md)等并发场景。详细请参见[多线程并发概述](multi-thread-concurrency-overview.md)。 在并发多线程场景下,不同线程间需要进行数据通信。不同类别的对象采用不同的传输方式,如拷贝或内存共享。 -并发能力广泛应用于多种场景,包括[异步并发任务](async-concurrency-overview.md)、[耗时任务](time-consuming-task-overview.md)(如[CPU密集型任务](cpu-intensive-task-development.md)、[I/O密集型任务](io-intensive-task-development.md)和[同步任务](sync-task-development.md)等)、[长时任务](long-time-task-overview.md)、[常驻任务](resident-task-overview.md)等。开发者可以根据不同的任务诉求和场景,选择相应的并发策略进行优化和开发,具体案例可以参见[应用多线程开发实践案例](batch-database-operations-guide.md)。 +并发能力广泛应用于多种场景,包括[异步并发任务](async-concurrency-overview.md)、[耗时任务](time-consuming-task-overview.md)(如[CPU密集型任务](cpu-intensive-task-development.md)、[I/O密集型任务](io-intensive-task-development.md)和[同步任务](sync-task-development.md)等)、[长时任务](long-time-task-overview.md)、[常驻任务](resident-task-overview.md)等。开发者可以根据不同的任务诉求和场景,选择相应的并发策略进行优化和开发,具体案例可以参见[应用多线程开发实践案例](batch-database-operations-guide.md)。 \ No newline at end of file diff --git a/zh-cn/application-dev/arkts-utils/interthread-communication-overview.md b/zh-cn/application-dev/arkts-utils/interthread-communication-overview.md index 80b71d478afe84322dc54435c5b1f63e5c4f9503..d14dcc4472283bc6361021e6e84321e47a6995ec 100644 --- a/zh-cn/application-dev/arkts-utils/interthread-communication-overview.md +++ b/zh-cn/application-dev/arkts-utils/interthread-communication-overview.md @@ -1,18 +1,18 @@ # ArkTS线程间通信概述 -线程间通信指的是并发多线程间存在的数据交换行为。由于ArkTS语言兼容TS/JS,其运行时的实现与其它所有的JS引擎一样,都是基于Actor内存隔离的并发模型提供并发能力。 +线程间通信指并发多线程间的数据交换行为。由于ArkTS语言兼容TS/JS,其运行时实现与其它JS引擎一样,采用基于Actor内存隔离的并发模型。 -在ArkTS线程间通信中,不同数据对象的行为存在差异。例如,普通JS对象、ArrayBuffer对象和SharedArrayBuffer对象在跨线程时的行为不一致,包括序列化和反序列化、数据转移和数据共享等操作。 +在ArkTS线程间通信中,不同数据对象的行为存在差异。例如,普通JS对象、ArrayBuffer对象和SharedArrayBuffer对象在跨线程时的处理方式不同,涉及序列化、反序列化、数据转移和数据共享等操作。 -以JS对象为例,其在并发任务间的通信采用了标准的Structured Clone算法(序列化和反序列化)。该算法通过序列化将JS对象转换为与引擎无关的数据(如字符串或内存块),在另一个并发实例中通过反序列化还原成与原JS对象内容一致的新对象。因此,需要进行深拷贝,效率较低。除了支持JS标准的序列化和反序列化能力,还支持绑定Native的JS对象的传输,以及[Sendable对象](arkts-sendable.md)的共享能力。 +以JS对象为例,其在并发任务间的通信采用了标准的Structured Clone算法(序列化和反序列化)。该算法通过序列化将JS对象转换为与引擎无关的数据(如字符串或内存块),在另一个并发任务中通过反序列化还原成与原JS对象内容一致的新对象。因此,需要进行深拷贝,效率较低。除了支持JS标准的序列化和反序列化能力,还支持绑定Native的JS对象的传输,以及[Sendable对象](arkts-sendable.md)的共享能力。 ArkTS目前主要提供两种并发能力支持线程间通信:TaskPool和Worker。 - Worker是Actor并发模型标准的跨线程通信API,与Web Worker或者Node.js Worker的使用方式基本一致。 -- TaskPool提供了功能更强、并发编程更简易的任务池API。其中TaskPool涉及跨并发实例的对象传递行为与Worker一致,还是采用了标准的Structured Clone算法,并发通信的对象越大,耗时就越长。 +- TaskPool提供了功能更强、并发编程更简易的任务池API。其中TaskPool涉及跨并发任务的对象传递行为与Worker一致,还是采用了标准的Structured Clone算法,并发通信的对象越大,耗时就越长。 -基于ArkTS提供的TaskPool和Worker并发接口,支持多种线程间通信能力,可以满足开发者的不同[线程间通信场景](independent-time-consuming-task.md)。如独立的耗时任务、多个耗时任务、TaskPool线程与宿主线程通信、Worker线程与宿主线程的异步通信、Worker同步调用宿主线程的接口等。同时,基于[Node-API](../napi/napi-introduction.md)提供的机制,C++线程可以跨线程调用ArkTS接口。 +基于ArkTS提供的TaskPool和Worker并发接口,支持多种线程间通信能力,可以满足不同[线程间通信场景](independent-time-consuming-task.md)。如独立的耗时任务、多个耗时任务、TaskPool线程与宿主线程通信、Worker线程与宿主线程的异步通信、Worker同步调用宿主线程的接口等。此外,通过[Node-API](../napi/napi-introduction.md)机制,C++线程可以跨线程调用ArkTS接口。 图1 序列化反序列化原理图 diff --git a/zh-cn/application-dev/arkts-utils/multi-thread-concurrency-overview.md b/zh-cn/application-dev/arkts-utils/multi-thread-concurrency-overview.md index b99872682b9d0d7e1a6266c40655572e3a4524b6..568b9fd5e14b45cd3a45a86c0588f1aad89d5c5b 100644 --- a/zh-cn/application-dev/arkts-utils/multi-thread-concurrency-overview.md +++ b/zh-cn/application-dev/arkts-utils/multi-thread-concurrency-overview.md @@ -1,17 +1,17 @@ # 多线程并发概述 -多线程并发是指​​在单个程序中同时运行多个线程,通过并行或交替执行任务来提升性能和资源利用率​​的编程模型。在ArkTS应用开发过程中,需要用到多线程并发的业务场景有很多,针对常见的业务场景,主要可以分为以下三类,更详细的使用请参考[多线程开发实践案例](batch-database-operations-guide.md)。 +多线程并发是指在单个程序中同时运行多个线程,通过并行或交替执行任务来提升性能和资源利用率的编程模型。在ArkTS应用开发中,多线程并发适用于多种业务场景,常见的业务场景主要分为以下三类。更详细的使用请参考[多线程开发实践案例](batch-database-operations-guide.md)。 -- 业务逻辑包含较大计算量或多次I/O读写等需要长时间执行的任务,例如图片/视频编解码,压缩/解压缩,数据库操作等场景。 +- 业务逻辑包含大量计算或频繁的I/O读写等需要长时间执行的任务,例如图片和视频的编解码、文件的压缩与解压缩、数据库操作等场景。 -- 业务逻辑包含监听或定期采集数据等需要长时间保持运行的任务,例如定期采集传感器数据场景。 +- 业务逻辑包括监听和定期采集数据等需要长时间保持运行的任务,例如定期采集传感器数据的场景。 -- 业务逻辑跟随主线程生命周期或与主线程绑定的任务,例如游戏中台场景。 +- 业务逻辑跟随主线程的生命周期,或与主线程绑定的任务,例如在游戏中的业务场景。 并发模型用于实现不同应用场景中的并发任务。常见的并发模型有基于内存共享的模型和基于消息通信的模型。 -Actor并发模型是基于消息通信的并发模型的典型代表。它使开发者无需处理锁带来的复杂问题,并且具有较高的并发度,因此得到了广泛的应用。 +Actor并发模型是基于消息通信的典型并发模型。它使开发者无需处理锁带来的复杂问题,且具备高并发度,因此应用广泛。 当前ArkTS提供了TaskPool和Worker两种并发能力,两者均基于Actor并发模型实现。 @@ -23,11 +23,11 @@ Actor并发模型和内存共享并发模型的具体对比请见[多线程并 Actor并发模型每一个线程都是一个独立Actor,每个Actor有自己独立的内存,Actor之间通过消息传递机制触发对方Actor的行为,不同Actor之间不能直接访问对方的内存空间。 -Actor并发模型相较于内存共享并发模型,不同线程间的内存是隔离的,因此不会出现线程竞争同一内存资源的情况。开发者无需处理内存上锁相关的问题,从而提高开发效率。 +Actor并发模型与内存共享并发模型相比,不同线程间的内存是隔离的,因此不会发生线程竞争同一内存资源的情况。无需处理内存上锁问题,从而提高开发效率。 -Actor并发模型中,线程不共享内存,需通过线程间通信机制传递任务和结果。 +Actor并发模型中,不同Actor之间不共享内存,需通过消息传递机制传递任务和结果。 -本文以经典的生产者消费者问题为例,对比呈现这两种模型在解决具体问题时的差异。 +本文以经典的生产者消费者问题为例,对比这两种模型在解决问题时的差异。 ### 内存共享模型 @@ -35,7 +35,7 @@ Actor并发模型中,线程不共享内存,需通过线程间通信机制传 ![zh-cn_image_0000002001497485](figures/zh-cn_image_0000002001497485.png) -为了避免不同生产者或消费者同时访问一块共享内存的容器时产生的脏读、脏写现象,同一时间只能有一个生产者或消费者访问该容器,也就是不同生产者和消费者争夺使用容器的锁。当一个角色获取锁之后其他角色需要等待该角色释放锁之后才能重新尝试获取锁以访问该容器。 +为了避免不同生产者或消费者同时访问同一块共享内存容器时产生脏读、脏写现象,同一时间只能有一个生产者或消费者访问该容器。即不同生产者和消费者需争夺使用容器的锁。当一个角色获取锁后,其他角色需等待该角色释放锁,才能重新尝试获取锁以访问该容器。 ```ts // 此段示例为伪代码仅作为逻辑示意,便于开发者理解使用内存共享模型和Actor模型的区别 @@ -142,7 +142,7 @@ function Main(): void { ![zh-cn_image_0000001964697544](figures/zh-cn_image_0000001964697544.png) -Actor模型中,不同角色之间并不共享内存,生产者线程和UI线程都有自己的虚拟机实例,两个虚拟机实例之间拥有独占的内存,相互隔离。生产者生产出结果后,通过序列化通信将结果发送给UI线程,UI线程消费结果后再发送新的生产任务给生产者线程。 +Actor模型中,不同角色之间并不共享内存,生产者线程和UI线程都有自己的虚拟机实例,两个虚拟机实例之间拥有独占的内存,相互隔离。生产者生产出结果后,通过序列化通信将结果发送给UI线程。UI线程消费结果后,再发送新的生产任务给生产者线程。 ```ts import { taskpool } from '@kit.ArkTS'; @@ -198,7 +198,7 @@ struct Index { ``` -也可以等待生产者完成所有生产任务,通过序列化通信将结果发送给UI线程。UI线程接收完毕后,由消费者统一消费结果。 +也可以等待生产者完成所有任务,通过序列化通信将结果发送给UI线程。UI线程接收后,由消费者统一消费结果。 ```ts import { taskpool } from '@kit.ArkTS'; diff --git a/zh-cn/application-dev/arkts-utils/normal-object.md b/zh-cn/application-dev/arkts-utils/normal-object.md index 2f68dec2de417516041964fa9b3a59343e20cf72..16bbd4a6d6353a428d9a468e92dce9bd5334335f 100644 --- a/zh-cn/application-dev/arkts-utils/normal-object.md +++ b/zh-cn/application-dev/arkts-utils/normal-object.md @@ -1,12 +1,12 @@ # 普通对象 -普通对象跨线程时通过拷贝形式传递,两个线程的对象内容一致,但是指向各自线程的隔离内存区间,被分配在各自线程的虚拟机本地堆(LocalHeap)。例如,Ecmascript262规范定义的Object、Array、Map等对象通过这种方式实现跨并发实例通信。通信过程如图所示: +普通对象跨线程时通过拷贝形式传递,两个线程的对象内容一致,但指向各自线程的隔离内存区间,被分配在各自线程的虚拟机本地堆(LocalHeap)。例如,Ecmascript 262规范定义的Object、Array、Map等对象通过这种方式实现跨并发实例通信。通信过程如图所示: ![deep_copy](figures/deep_copy.png) > **说明:** > -> 普通类实例对象跨线程通过拷贝形式传递,只能传递数据,类实例上的方法会丢失。可以使用[@Sendable装饰器](arkts-sendable.md#sendable装饰器)标识为Sendable类,类实例对象跨线程传递后,可携带类方法。 +> 普通类实例对象跨线程通过拷贝形式传递,只能传递数据,类实例上的方法会丢失。使用[@Sendable装饰器](arkts-sendable.md#sendable装饰器)标识为Sendable类后,类实例对象跨线程传递后,可携带类方法。 ## 使用示例 diff --git a/zh-cn/application-dev/arkts-utils/sendable-constraints.md b/zh-cn/application-dev/arkts-utils/sendable-constraints.md index 1a6d3a0af0c547df6dc7e41720e334521c55662d..967a01fbeff763b9c2c753f8420140a46de0b8b6 100644 --- a/zh-cn/application-dev/arkts-utils/sendable-constraints.md +++ b/zh-cn/application-dev/arkts-utils/sendable-constraints.md @@ -4,7 +4,7 @@ ### Sendable类必须继承自Sendable类 -Sendable对象的布局和原型链不可变,而非Sendable对象可以通过特殊方式修改布局。因此,不允许互相继承。这里的类不包括变量,Sendable类不能继承自变量。 +Sendable对象的布局和原型链不可变,而非Sendable对象可以通过特殊方式修改布局。因此,不允许互相继承。这里的类不包含变量,Sendable类不能继承自变量。 **正例:** @@ -43,7 +43,7 @@ class B extends A { // A不是sendable class,B不能继承它,编译报错 ### 非Sendable类必须继承自非Sendable类 -Sendable对象的布局及原型链不可变,而非Sendable对象可以通过特殊方式修改布局,因此不允许互相继承。 +Sendable对象的布局和原型链不可变,而非Sendable对象可以通过特殊方式修改布局,因此不允许互相继承。 **正例:** @@ -81,7 +81,7 @@ class B extends A { // A是sendable class,B不能继承它,编译报错 ### 非Sendable类禁止实现Sendable接口 -如果非Sendable类实现Sendable接口,可能会被误认为是Sendable类,从而导致错误使用。 +非Sendable类实现Sendable接口时,可能被误认为是Sendable类,导致错误使用。 **正例:** @@ -108,7 +108,7 @@ class B implements I {}; // I是sendable interface,B不能实现,编译报 ### 必须是Sendable支持的数据类型 -Sendable数据不能持有非Sendable数据,因此Sendable类或接口的成员变量必须是[Sendable支持的数据类型](arkts-sendable.md#sendable支持的数据类型)。 +Sendable数据不得持有非Sendable数据,因此Sendable类或接口的成员变量必须是[Sendable支持的数据类型](arkts-sendable.md#sendable支持的数据类型)。 **正例:** @@ -136,7 +136,7 @@ class A { ### 不支持使用!断言 -Sendable对象的成员属性必须赋初值,“!”修饰的变量可以不赋初值,因此不支持使用“!” 。 +Sendable对象的成员属性必须赋初值,而“!”修饰的变量可以不赋初值,因此不支持使用“!”。 **正例:** @@ -164,7 +164,7 @@ class A { ### 不支持使用计算属性名 -Sendable对象的布局不可变,计算属性无法静态确定对象布局,因此不支持。 +Sendable对象的布局不可更改,因为计算属性无法静态确定对象布局,所以不支持。 **正例:** @@ -337,7 +337,7 @@ type D = C; // 编译报错 ### Sendable类和Sendable函数禁止使用除\@Sendable外的装饰器 -如果在ts文件中定义类装饰器,可能会修改类的布局,从而导致运行时错误。 +在ts文件中定义类装饰器时,可能会改变类的结构,进而引发运行时错误。 **正例:** @@ -363,7 +363,7 @@ class C { ### 禁止使用对象字面量/数组字面量初始化Sendable对象 -对象字面量和数组字面量不是Sendable类型,Sendable数据类型必须通过Sendable类型的new表达式创建。 +对象字面量和数组字面量不是Sendable类型。Sendable类型必须通过Sendable类型的new表达式创建。 **正例:** @@ -425,7 +425,7 @@ let a2: SendableA = new A() as SendableA; // 编译报错 ### 箭头函数不可标记为Sendable -箭头函数不支持\@Sendable装饰器,因此它是非Sendable函数,不支持共享。 +箭头函数不支持\@Sendable装饰器,因此它是非Sendable函数,因此不支持共享。 **正例:** @@ -470,8 +470,8 @@ class SendableClass { | 规则 | | -------- | | Sendable对象传入TS/JS的接口中,禁止操作其对象布局(增、删属性,改变属性类型)。 | -| Sendable对象设置到TS/JS的对象上,TS中获取到这个Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。 | -| Sendable对象放入TS/JS的容器中,TS中获取到这个Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。 | +| Sendable对象设置到TS/JS的对象上,TS中获取到Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。 | +| Sendable对象放入TS/JS的容器中,TS中获取到Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。 | > **说明:** > @@ -484,10 +484,10 @@ NAPI相关接口请参考[Sendable相关的NAPI接口](../napi/use-napi-about-ex | 规则 | | -------- | -| 禁止删除属性,不能使用的接口有:napi_delete_property。 | -| 禁止新增属性,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。 | -| 禁止修改属性类型,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。 | -| 不支持Symbol相关接口和类型,不能使用的接口有:napi_create_symbol、napi_is_symbol_object、napi_symbol。 | +| 禁止删除属性。不能使用napi_delete_property接口。 | +| 禁止新增属性。不能使用napi_set_property、napi_set_named_property、napi_define_properties接口。 | +| 禁止修改属性类型。不能使用napi_set_property、napi_set_named_property、napi_define_properties接口。 | +| 不支持Symbol相关接口和类型。不能使用napi_create_symbol、napi_is_symbol_object、napi_symbol接口。 | ## 与UI交互的规则 @@ -497,4 +497,4 @@ Sendable数据需要与[makeObserved](../ui/state-management/arkts-new-makeObser ## 在HAR包中的使用规则 -HAR中使用Sendable时,需开启编译生成TS文件的配置。具体使用请参考[编译生成TS文件](../quick-start/har-package.md#编译生成ts文件)。 +HAR中使用Sendable时,需启用编译生成TS文件的配置。具体使用请参考[编译生成TS文件](../quick-start/har-package.md#编译生成ts文件)。 diff --git a/zh-cn/application-dev/arkts-utils/shared-arraybuffer-object.md b/zh-cn/application-dev/arkts-utils/shared-arraybuffer-object.md index 26e38654e0b8055ac7509512dbc87fcc0e8501b6..81ca68dcb5ba72595674ac291c1551e66ce90083 100644 --- a/zh-cn/application-dev/arkts-utils/shared-arraybuffer-object.md +++ b/zh-cn/application-dev/arkts-utils/shared-arraybuffer-object.md @@ -1,13 +1,13 @@ # SharedArrayBuffer对象 -SharedArrayBuffer内部包含一块Native内存,其JS对象壳被分配在虚拟机本地堆(LocalHeap)。支持跨并发实例间共享Native内存,但是对共享Native内存的访问及修改需要采用Atomics类,防止数据竞争。SharedArrayBuffer可以用于多个并发实例间的状态共享或者数据共享。通信过程如下图所示: +SharedArrayBuffer内部包含一块Native内存,其JS对象壳被分配在虚拟机本地堆(LocalHeap)。支持跨并发实例间共享Native内存,但是对共享Native内存的访问及修改需要采用Atomics类,防止数据竞争。SharedArrayBuffer可用于多个并发实例间的状态或数据共享。通信过程如下图所示: ![sharedarraybufer](figures/sharedarraybufer.png) ## 使用示例 -这里提供了一个示例,使用TaskPool传递Int32Array对象,实现如下: +使用TaskPool传递Int32Array对象,实现如下: ```ts import { taskpool } from '@kit.ArkTS'; diff --git a/zh-cn/application-dev/arkts-utils/taskpool-introduction.md b/zh-cn/application-dev/arkts-utils/taskpool-introduction.md index 3521ff05b952d9197f55e4da6ab4615440ec30a5..b502a30e19211c65cd95eaaccdec0ecdb00240a7 100644 --- a/zh-cn/application-dev/arkts-utils/taskpool-introduction.md +++ b/zh-cn/application-dev/arkts-utils/taskpool-introduction.md @@ -1,6 +1,6 @@ # TaskPool简介 -TaskPool为应用程序提供多线程环境,降低资源消耗、提高系统性能,无需管理线程生命周期。具体接口信息及使用方法详情请见[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)。 +TaskPool为应用程序提供多线程环境,降低资源消耗并提高系统性能。无需管理线程生命周期。具体接口信息及使用方法,请参见[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)。 ## TaskPool运作机制 @@ -8,7 +8,7 @@ TaskPool运作机制示意图 ![zh-cn_image_0000001964858368](figures/zh-cn_image_0000001964858368.png) -TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择合适的工作线程执行任务,再将结果返回给宿主线程。接口易用,支持任务执行、取消和指定优先级,同时通过系统统一线程管理,结合动态调度及负载均衡算法,可以节约系统资源。系统默认启动一个任务工作线程,任务多时会扩容。工作线程数量上限取决于设备的物理核数,内部管理具体数量,确保调度和执行效率最优。长时间无任务分发时会缩容,减少工作线程数量。具体扩缩容机制详情请见[TaskPool扩缩容机制](taskpool-introduction.md#taskpool扩缩容机制)。 +TaskPool支持在宿主线程提交任务到任务队列,系统选择合适的工作线程执行任务,并将结果返回给宿主线程。接口易用,支持任务执行、取消和指定优先级。通过系统统一线程管理,结合动态调度和负载均衡算法,可以节约系统资源。系统默认启动一个任务工作线程,任务多时会自动扩容。工作线程数量上限由设备的物理核数决定,内部管理具体数量,确保调度和执行效率最优。长时间无任务分发时会缩容,减少工作线程数量。具体扩缩容机制请参见[TaskPool扩缩容机制](taskpool-introduction.md#taskpool扩缩容机制)。 ## TaskPool注意事项 @@ -16,9 +16,9 @@ TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择 - 从API version 11开始,跨并发实例传递带方法的实例对象时,该类必须使用装饰器[@Sendable装饰器](arkts-sendable.md#sendable装饰器)标注,且仅支持在.ets文件中使用。 -- 任务函数([LongTask](../reference/apis-arkts/js-apis-taskpool.md#longtask12)除外)在TaskPool工作线程的执行耗时不能超过3分钟(不包含Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时)。否则,任务将被强制终止。 +- 任务函数([LongTask](../reference/apis-arkts/js-apis-taskpool.md#longtask12)除外)在TaskPool工作线程的运行耗时不能超过3分钟(不包含Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时)。否则,任务将被强制终止。 -- 实现任务的函数入参需满足序列化支持的类型,详情请参见[线程间通信对象](interthread-communication-overview.md)。目前不支持使用[@State装饰器](../ui/state-management/arkts-state.md)、[@Prop装饰器](../ui/state-management/arkts-prop.md)、[@Link装饰器](../ui/state-management/arkts-link.md)等装饰器修饰的复杂类型。 +- 实现任务的函数入参需满足序列化支持的类型。详情请参见[线程间通信对象](interthread-communication-overview.md)。目前不支持使用[@State装饰器](../ui/state-management/arkts-state.md)、[@Prop装饰器](../ui/state-management/arkts-prop.md)、[@Link装饰器](../ui/state-management/arkts-link.md)等装饰器修饰的复杂类型。 - ArrayBuffer参数在TaskPool中默认转移,需要设置转移列表的话可通过接口[setTransferList()](../reference/apis-arkts/js-apis-taskpool.md#settransferlist10)设置。如果需要多次调用使用ArrayBuffer作为参数的task,则需要通过接口[setCloneList()](../reference/apis-arkts/js-apis-taskpool.md#setclonelist11)把ArrayBuffer在线程中的传输行为改成拷贝传递,避免对原有对象产生影响。 @@ -47,7 +47,7 @@ TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择 } ``` -- 由于不同线程中上下文对象是不同的,因此TaskPool工作线程只能使用线程安全的库,例如UI相关的非线程安全库不能使用。 +- 由于不同线程中上下文对象不同,TaskPool工作线程只能使用线程安全的库。例如,不能使用UI相关的非线程安全库。 - 序列化传输的数据量限制为16MB。 @@ -57,13 +57,13 @@ TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择 - 不支持在TaskPool工作线程中使用[AppStorage](../ui/state-management/arkts-appstorage.md)。 -- TaskPool支持开发者在宿主线程封装任务并提交给任务队列,理论上支持的任务数量没有上限。然而,任务的执行效率受限于任务的优先级和系统资源。当工作线程达到最大数量时,任务的执行效率可能会下降。 +- TaskPool支持在宿主线程封装任务并提交给任务队列,理论上支持的任务数量没有上限。然而,任务的执行效率受限于任务的优先级和系统资源。当工作线程达到最大数量时,任务的执行效率可能会下降 - TaskPool不支持指定任务所运行的线程,任务会被分配到空闲的线程中执行。如果需要指定任务所运行的线程,建议使用[Worker](worker-introduction.md)。 ## \@Concurrent装饰器 -在使用[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)时,执行的并发函数需要使用该装饰器修饰,否则无法通过相关校验。 +使用[TaskPool](../reference/apis-arkts/js-apis-taskpool.md)时,执行的并发函数必须用该装饰器修饰,否则无法通过校验。 > **说明:** > @@ -75,8 +75,8 @@ TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择 | -------- | -------- | | 装饰器参数 | 无。 | | 使用场景 | 仅支持在Stage模型的工程中使用。仅支持在.ets文件中使用。 | -| 装饰的函数类型 | 允许标注async函数或普通函数。禁止标注generator、箭头函数、类方法。不支持类成员函数或者匿名函数。 | -| 装饰的函数内的变量类型 | 允许使用local变量、入参和通过import引入的变量。禁止使用闭包变量。 | +| 装饰的函数类型 | 允许标注为async函数或普通函数。禁止标注为generator、箭头函数、类方法。不支持类成员函数或者匿名函数。 | +| 装饰的函数内的变量类型 | 允许使用局部变量、入参和通过import引入的变量,禁止使用闭包变量。 | | 装饰的函数内的返回值类型 | 支持的类型请查[线程间通信对象](interthread-communication-overview.md)。 | > **说明:** @@ -143,7 +143,7 @@ struct Index { #### 并发函数返回Promise -并发函数中返回Promise时需要特别关注。如示例所示,testPromise和testPromise1等需处理Promise并返回结果。 +在并发函数中返回Promise时需特别注意。如示例所示,testPromise和testPromise1等函数需处理Promise并返回结果。 示例: @@ -255,7 +255,7 @@ struct Index { #### 并发函数中使用自定义类或函数 -在并发函数中使用自定义类或函数时,需将其定义在不同的文件中,否则会被认为是闭包。如以下示例所示。 +在并发函数中使用自定义类或函数时,需将其定义在单独的文件中,否则可能被视为闭包。如下示例所示。 示例: @@ -357,7 +357,7 @@ export class MyTestB { #### 并发异步函数中使用Promise -在并发异步函数中使用Promise时,建议搭配await使用。这样TaskPool可以捕获Promise中的异常。推荐使用示例如下。 +在并发异步函数中使用Promise时,建议搭配await使用,这样TaskPool可以捕获Promise中的异常。推荐使用示例如下。 示例: @@ -436,11 +436,11 @@ struct Index { ### 扩容机制 -一般情况下,开发者向任务队列提交任务时会触发扩容检测。扩容检测首先判断当前空闲的工作线程数是否大于任务数,如果大于,说明线程池中存在空闲工作线程,无需扩容。否则,通过负载计算确定所需工作线程数并创建。 +一般情况下,向任务队列提交任务时会触发扩容检测。扩容检测首先判断当前空闲工作线程数是否大于任务数。如果大于,说明线程池中有空闲工作线程,无需扩容。否则,通过负载计算确定所需工作线程数并创建。 ### 缩容机制 -扩容后,TaskPool新建多个工作线程,但当任务数减少后,这些线程就会处于空闲状态,造成资源浪费,因此TaskPool提供缩容机制。TaskPool使用了定时器,定时检测当前负载。定时器30s触发一次,每次尝试释放空闲的工作线程。释放的线程需要满足如下条件: +扩容后,TaskPool创建多个工作线程,但当任务数减少后,这些线程就会处于空闲状态,造成资源浪费,因此,TaskPool提供了缩容机制。TaskPool使用定时器,每30秒检测一次当前负载,并尝试释放空闲的工作线程。释放的线程需满足以下条件: - 该线程空闲时长达到30s。 diff --git a/zh-cn/application-dev/arkts-utils/taskpool-vs-worker.md b/zh-cn/application-dev/arkts-utils/taskpool-vs-worker.md index 697cc9291d68be724e2f2b1f5b864b858f228013..14634ef93dded7cfabb910a7b331df0672534141 100644 --- a/zh-cn/application-dev/arkts-utils/taskpool-vs-worker.md +++ b/zh-cn/application-dev/arkts-utils/taskpool-vs-worker.md @@ -1,10 +1,10 @@ # TaskPool和Worker的对比 (TaskPool和Worker) -TaskPool和Worker的作用是为应用程序提供一个多线程的运行环境,用于处理耗时的计算任务或其他密集型任务。可以避免任务阻塞宿主线程,从而提高系统性能和资源利用率。 +TaskPool和Worker的作用是为应用程序提供多线程运行环境,用于处理耗时计算任务或其他密集型任务,避免任务阻塞宿主线程,提高系统性能和资源利用率。 -本文将从[实现特点](#实现特点对比)和[适用场景](#适用场景对比)两个方面来进行TaskPool与Worker的比较。 +本文将从[实现特点](#实现特点对比)和[适用场景](#适用场景对比)两个方面比较TaskPool与Worker。 ## 实现特点对比 @@ -16,12 +16,12 @@ TaskPool和Worker的作用是为应用程序提供一个多线程的运行环境 | 内存模型 | 线程间隔离,内存不共享。 | 线程间隔离,内存不共享。 | | 参数传递机制 | 采用标准的结构化克隆算法(Structured Clone)进行序列化、反序列化,完成参数传递。
支持ArrayBuffer转移、SharedArrayBuffer共享和Sendable引用传递。 | 采用标准的结构化克隆算法(Structured Clone)进行序列化、反序列化,完成参数传递。
支持ArrayBuffer转移、SharedArrayBuffer共享和Sendable引用传递。 | | 参数传递 | 直接传递,无需封装。 | 消息对象唯一参数,需要自己封装。 | -| 方法调用 | 直接将\@Concurrent修饰的方法传入并调用。 | 在Worker线程中解析消息并调用对应方法。 | +| 方法调用 | 直接传入并调用\@Concurrent修饰的方法。 | 在Worker线程中解析消息并调用对应方法。 | | 返回值 | 异步调用后默认返回。 | 主动发送消息,需在onmessage中解析并赋值。 | -| 生命周期 | TaskPool自行管理生命周期,无需关心任务负载高低。 | 开发者自行管理Worker的数量及生命周期。 | +| 生命周期 | TaskPool自动管理其生命周期,无需关注任务负载。 | 开发者需自行管理Worker的数量和生命周期。 | | 任务池个数上限 | 自动管理,无需配置。 | 同个进程下,最多支持同时开启64个Worker线程,实际数量由进程内存决定。 | | 任务执行时长上限 | 3分钟(不包含Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时),长时任务无执行时长上限。 | 无限制。 | -| 设置任务的优先级 | 支持配置任务优先级。 | 从API version 18 开始,支持配置Worker线程的优先级。 | +| 设置任务的优先级 | 支持配置任务优先级。 | 从API version 18开始,支持配置Worker线程优先级。 | | 执行任务的取消 | 支持取消已经发起的任务。 | 不支持。 | | 线程复用 | 支持。 | 不支持。 | | 任务延时执行 | 支持。 | 不支持。 | @@ -36,16 +36,16 @@ TaskPool和Worker的作用是为应用程序提供一个多线程的运行环境 TaskPool和Worker均支持多线程并发能力。由于TaskPool的工作线程会绑定系统的调度优先级,并支持负载均衡(自动扩缩容),相比之下,Worker需要开发者自行创建,存在创建耗时。因此,性能方面TaskPool优于Worker,推荐在大多数场景中使用TaskPool。 -TaskPool偏向独立任务维度,该任务在线程中执行,无需关注线程的生命周期,超长任务(大于3分钟且非长时任务)会被系统自动回收。而Worker偏向线程的维度,支持长时间占据线程执行,需要开发者主动管理线程生命周期。 +TaskPool偏向于独立任务,任务在线程中执行时,无需关注线程的生命周期。超长任务(大于3分钟且非长时任务)会被系统自动回收。而Worker适用于长时间占据线程的任务,需要开发者主动管理线程的生命周期。 常见开发场景及适用说明如下: - 运行时间超过3分钟的任务(不包括Promise和async/await异步调用的耗时,如网络下载、文件读写等I/O任务的耗时):例如后台进行1小时的预测算法训练等CPU密集型任务,需要使用Worker。场景示例可参考[常驻任务开发指导](resident-task-guide.md)。 -- 有关联的一系列同步任务:例如在一些需要创建、使用句柄的场景中,句柄每次创建都是不同的,该句柄需永久保存,保证使用该句柄进行操作,需要使用Worker。场景示例可参考[使用Worker处理关联的同步任务](sync-task-development.md#使用worker处理关联的同步任务)。 +- 有关联的一系列同步任务:例如在一些需要创建、使用句柄的场景中,每次创建的句柄都不同,必须永久保存该句柄,以确保后续操作正确执行,需要使用Worker。场景示例可参考[使用Worker处理关联的同步任务](sync-task-development.md#使用worker处理关联的同步任务)。 -- 需要设置优先级的任务:在API version 18 之前,Worker不支持设置调度优先级,需要使用TaskPool。从API version 18 开始,Worker支持设置调度优先级,开发者可以根据使用场景和任务特性选择使用TaskPool或Worker。例如[图库直方图绘制场景](cpu-intensive-task-development.md#使用taskpool进行图像直方图处理),后台计算的直方图数据会用于前台界面的显示,影响用户体验,需要高优先级处理,且任务相对独立,推荐使用TaskPool。 +- 需要设置优先级的任务:在API version 18 之前,Worker不支持设置调度优先级,需要使用TaskPool。从API version 18开始,Worker支持设置调度优先级,开发者可以根据使用场景和任务特性选择使用TaskPool或Worker。例如[图库直方图绘制场景](cpu-intensive-task-development.md#使用taskpool进行图像直方图处理),后台计算的直方图数据会用于前台界面的显示,影响用户体验,需要高优先级处理,且任务相对独立,推荐使用TaskPool。 -- 需要频繁取消的任务:例如图库大图浏览场景,为提升体验,会同时缓存当前图片左右侧各2张图片,往一侧滑动跳到下一张图片时,要取消另一侧的一个缓存任务,需要使用TaskPool。 +- 需要频繁取消的任务:如图库大图浏览场景。为提升体验,系统会同时缓存当前图片左右各两张图片。当往一侧滑动跳到下一张图片时,需取消另一侧的缓存任务,此时需使用TaskPool。 -- 大量或调度点分散的任务:例如大型应用的多个模块包含多个耗时任务,不方便使用Worker去做负载管理,推荐使用TaskPool。场景示例可参考[批量数据写数据库场景](batch-database-operations-guide.md)。 +- 大量或调度点分散的任务:例如大型应用中的多个模块包含多个耗时任务,不建议使用Worker进行负载管理,推荐使用TaskPool。场景示例可参考[批量数据写数据库场景](batch-database-operations-guide.md)。 diff --git a/zh-cn/application-dev/arkts-utils/transferabled-object.md b/zh-cn/application-dev/arkts-utils/transferabled-object.md index ef4bbcdf5f9a29bb65abec63dffb7b819b8891b0..fa0d43ce4a13ca3745899e5cedd9d8e16cc8082f 100644 --- a/zh-cn/application-dev/arkts-utils/transferabled-object.md +++ b/zh-cn/application-dev/arkts-utils/transferabled-object.md @@ -1,25 +1,25 @@ # Transferable对象(NativeBinding对象) -Transferable对象,也称为NativeBinding对象,是指绑定C++对象的JS对象,主体功能由C++提供,其JS对象壳被分配在虚拟机本地堆(LocalHeap)。跨线程传输时复用同一个C++对象,相比于JS对象的拷贝模式,传输效率高。因此,可共享或转移的NativeBinding对象也被称为Transferable对象。开发者也可以自定义Transferable对象,详细示例请参考[自定义Native Transferable对象的多线程操作场景](napi-coerce-to-native-binding-object.md)。 +Transferable对象,也称为NativeBinding对象,是指绑定C++对象的JS对象,其主要功能由C++提供,JS对象壳则分配在虚拟机的本地堆(LocalHeap)中。跨线程传输时复用同一个C++对象,相比JS对象的拷贝模式,传输效率更高。因此,可共享或转移的NativeBinding对象被称为Transferable对象。开发者可以自定义Transferable对象,详细示例请参考[自定义Native Transferable对象的多线程操作场景](napi-coerce-to-native-binding-object.md)。 ## 共享模式 -如果C++实现能够保证线程安全性,则这个NativeBinding对象的C++部分支持共享传输。此时,NativeBinding对象跨线程传输后,只需要重新创建JS壳,就可以桥接到同一个C++对象上,实现C++对象的共享。通信过程如下图所示: +如果C++实现能够确保线程安全性,则NativeBinding对象的C++部分支持跨线程共享。NativeBinding对象跨线程传输后,只需重新创建JS壳即可桥接到同一个C++对象上,实现C++对象的共享。通信过程如下图所示: ![nativeBinding](figures/nativeBinding.png) -常见的共享模式NativeBinding对象包括Context对象,它包含应用程序组件的上下文信息,提供访问系统服务和资源的方式,使得应用程序组件可以与系统进行交互。获取Context信息的方法可以参考[获取上下文信息](../application-models/application-context-stage.md)。 +常见的共享模式NativeBinding对象包括Context对象,它包含应用程序组件的上下文信息,提供访问系统服务和资源的方法,使应用程序组件能够与系统进行交互。获取Context信息的方法可以参考[获取上下文信息](../application-models/application-context-stage.md)。 示例可参考[使用TaskPool进行频繁数据库操作](batch-database-operations-guide.md#使用taskpool进行频繁数据库操作)。 ## 转移模式 -如果C++实现包含数据,且无法保证线程安全性,则NativeBinding对象的C++部分需要采用转移方式传输。NativeBinding对象跨线程传输后,重新创建JS壳即可桥接到C++对象上,但需移除原JS壳与C++对象的绑定关系。通信过程如下图所示: +如果C++实现包含数据且无法保证线程安全性,则NativeBinding对象的C++部分需要采用转移方式传输。NativeBinding对象跨线程传输后,重新创建JS壳可桥接到C++对象上,但需移除原JS壳与C++对象的绑定关系。通信过程如下图所示: ![nativeBinding_transfer](figures/nativeBinding_transfer.png) @@ -27,7 +27,7 @@ Transferable对象,也称为NativeBinding对象,是指绑定C++对象的JS ### 使用示例 -这里提供了一个跨线程传递PixelMap对象的示例以帮助更好理解。首先获取rawfile文件夹中的图片资源,然后在子线程中创建PixelMap对象传递给主线程,具体实现如下: +这里提供了一个跨线程传递PixelMap对象的示例。首先从rawfile文件夹中获取图片资源,然后在子线程中创建PixelMap对象并传递给主线程,具体实现如下: ```ts // Index.ets diff --git a/zh-cn/application-dev/arkts-utils/worker-introduction.md b/zh-cn/application-dev/arkts-utils/worker-introduction.md index fd100820ed8ddc01f813dc7f26563b269f43938e..7acd9bfeceb35594600dcd6ccfe061a03a1dd9eb 100644 --- a/zh-cn/application-dev/arkts-utils/worker-introduction.md +++ b/zh-cn/application-dev/arkts-utils/worker-introduction.md @@ -1,6 +1,6 @@ # Worker简介 -Worker的主要作用是为应用程序提供一个多线程的运行环境,满足应用程序在执行过程中与宿主线程分离,在后台线程中运行脚本进行耗时操作,避免计算密集型或高延迟的任务阻塞宿主线程。具体接口信息及使用方法详情请见[Worker](../reference/apis-arkts/js-apis-worker.md)。 +Worker的主要作用是为应用程序提供一个多线程的运行环境,实现应用程序执行过程与宿主线程分离。通过在后台线程运行脚本处理耗时操作,避免计算密集型或高延迟任务阻塞宿主线程。具体接口信息及使用方法详情请见[Worker](../reference/apis-arkts/js-apis-worker.md)。 ## Worker运作机制 @@ -14,16 +14,16 @@ Worker的主要作用是为应用程序提供一个多线程的运行环境, ## Worker注意事项 -- 创建Worker时,提供手动和自动两种创建方式,推荐使用自动创建方式。手动创建Worker线程目录及文件时,需同步进行相关配置,具体要求请参阅[创建Worker的注意事项](#创建worker的注意事项)。 -- 使用Worker能力时,构造函数中传入的Worker线程文件的路径在不同版本有不同的规则,详情请参见[文件路径注意事项](#文件路径注意事项)。 +- 创建Worker有手动和自动两种方式,推荐使用自动创建方式。手动创建Worker线程目录及文件时,需同步进行相关配置,具体要求请参阅[创建Worker的注意事项](#创建worker的注意事项)。 +- 使用Worker时,构造函数中传入的Worker线程文件路径在不同版本有不同的规则,详情请参见[文件路径注意事项](#文件路径注意事项)。 - Worker创建后需要手动管理生命周期。同时运行的Worker子线程数量最多为64个,并且与[napi_create_ark_runtime](../reference/native-lib/napi.md#napi_create_ark_runtime)创建的runtime总数不超过80。详情请参见[生命周期注意事项](#生命周期注意事项)。 - 不同线程中上下文对象是不同的,因此Worker线程只能使用线程安全的库,例如UI相关的非线程安全库不能在Worker子线程中使用。 - 单次序列化传输的数据量大小限制为16MB。 -- 使用Worker模块时,API version 18及之后的版本建议在宿主线程中注册onAllErrors回调,以捕获Worker线程生命周期内的各种异常。API version 18之前的版本应注册onerror回调。如果未注册onAllErrors或onerror回调,当Worker线程出现异常时会发生jscrash问题。需要注意的是,onerror接口仅能捕获onmessage回调中的同步异常,捕获异常后,Worker线程将进入销毁流程,无法继续使用。详情请参见[onAllErrors接口与onerror接口之间的行为差异](#onallerrors接口与onerror接口之间的行为差异)。 +- 使用Worker模块时,API version 18及之后的版本建议在宿主线程中注册onAllErrors回调,以捕获Worker线程生命周期内的各种异常。API version 18之前的版本应注册onerror回调。如果未注册onAllErrors或onerror回调,当Worker线程出现异常时会发生jscrash问题。注意,onerror接口仅能捕获onmessage回调中的同步异常,捕获异常后,Worker线程将进入销毁流程,无法继续使用。详情请参见[onAllErrors接口与onerror接口之间的行为差异](#onallerrors接口与onerror接口之间的行为差异)。 - 不支持跨HAP使用Worker线程文件。 - 引用HAR/HSP中的worker前,需要先配置对HAR/HSP的依赖,详见[引用共享包](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-har-import)。 - 不支持在Worker工作线程中使用[AppStorage](../ui/state-management/arkts-appstorage.md)。 -- 从API version 18开始,Worker线程优先级可以在构造函数的参数[WorkerOptions](../reference/apis-arkts/js-apis-worker.md#workeroptions)中进行指定。 +- 从API version 18开始,可以在构造函数的参数[WorkerOptions](../reference/apis-arkts/js-apis-worker.md#workeroptions)中指定Worker线程的优先级。 - 在Worker文件中禁止使用export语法导出任何内容,否则会导致jscrash问题。 @@ -63,7 +63,7 @@ Worker线程文件需要放在"{moduleName}/src/main/ets/"目录层级之下, ### 文件路径注意事项 - 当使用Worker模块具体功能时,均需先构造Worker实例对象,其构造函数与API版本相关,且构造函数需要传入Worker线程文件的路径(scriptURL)。 + 使用Worker模块的具体功能时,需先构造Worker实例对象。构造函数与API版本相关,且需传入Worker线程文件的路径(scriptURL)。 ```ts // 导入模块 @@ -83,9 +83,9 @@ const worker2: worker.Worker = new worker.Worker('entry/ets/workers/worker.ets') - scriptURL的组成包含{moduleName}/ets和相对路径relativePath。 - relativePath是Worker线程文件相对于"{moduleName}/src/main/ets/"目录的相对路径。 -1) 加载Ability中Worker线程文件场景 +1) 加载Ability中的Worker线程文件: -加载Ability中的worker线程文件,加载路径规则:{moduleName}/ets/{relativePath}。 +加载Ability中的worker线程文件。路径规则:{moduleName}/ets/{relativePath}。 ```ts import { worker } from '@kit.ArkTS'; @@ -97,9 +97,9 @@ const workerStage1: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/wor const workerStage2: worker.ThreadWorker = new worker.ThreadWorker('testworkers/ets/ThreadFile/workers/worker.ets'); ``` -2) 加载[HSP](../quick-start/in-app-hsp.md)中Worker线程文件场景 +2) 加载[HSP](../quick-start/in-app-hsp.md)中Worker线程文件 -加载HSP中worker线程文件,加载路径规则:{moduleName}/ets/{relativePath}。 +加载HSP中的worker线程文件。路径规则:{moduleName}/ets/{relativePath}。 ```ts import { worker } from '@kit.ArkTS'; @@ -108,13 +108,13 @@ import { worker } from '@kit.ArkTS'; const workerStage3: worker.ThreadWorker = new worker.ThreadWorker('hsp/ets/workers/worker.ets'); ``` -3) 加载[HAR](../quick-start/har-package.md)中Worker线程文件场景 +3) 加载[HAR](../quick-start/har-package.md)中Worker线程文件 加载HAR中worker线程文件存在以下两种情况: - @标识路径加载形式:所有种类的模块加载本地HAR中的Worker线程文件,加载路径规则:@{moduleName}/ets/{relativePath}。 -- 相对路径加载形式:本地HAR加载该包内的Worker线程文件,加载路径规则:创建Worker对象所在文件与Worker线程文件的相对路径。 +- 相对路径加载形式:本地HAR加载该包内的Worker线程文件,路径规则为:创建Worker对象所在文件与Worker线程文件的相对路径。 >**说明:** > @@ -156,25 +156,25 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke ### 生命周期注意事项 -- Worker的创建和销毁会消耗较多的系统资源,建议开发者合理管理已创建的Worker并重复使用。Worker空闲时仍会占用资源,因此当不需要Worker时,可以调用[terminate()](../reference/apis-arkts/js-apis-worker.md#terminate9)接口或[close()](../reference/apis-arkts/js-apis-worker.md#close9)方法主动销毁Worker。若Worker处于已销毁或正在销毁等非运行状态时,调用其功能接口,会抛出相应的错误。 +- Worker的创建和销毁会消耗较多的系统资源,建议开发者合理管理并重复使用已创建的Worker。Worker空闲时仍会占用资源,当不需要Worker时,可以调用[terminate()](../reference/apis-arkts/js-apis-worker.md#terminate9)接口或[close()](../reference/apis-arkts/js-apis-worker.md#close9)方法主动销毁Worker。若Worker处于已销毁或正在销毁等非运行状态时,调用其功能接口,会抛出相应的错误。 -- Worker的数量由内存管理策略决定,设定的内存阈值为1.5GB和设备物理内存的60%中的较小者。在内存允许的情况下,系统最多可以同时运行64个Worker。如果尝试创建的Worker数量超出这一上限,系统将抛出错误:“Worker initialization failure, the number of workers exceeds the maximum.”。实际运行的Worker数量会根据当前内存使用情况实时调整。当所有Worker和主线程的累积内存占用超过设定的阈值时,系统将触发内存溢出(OOM)错误,导致应用程序崩溃。 +- Worker的数量由内存管理策略决定,设定的内存阈值为1.5GB和设备物理内存的60%中的较小值。在内存允许的情况下,系统最多可以同时运行64个Worker。尝试创建的Worker数量超出上限时,系统将抛出错误:“Worker initialization failure, the number of workers exceeds the maximum.”。实际运行的Worker数量会根据当前内存使用情况实时调整。当所有Worker和主线程的累积内存占用超过设定的阈值时,系统将触发内存溢出(OOM)错误,导致应用程序崩溃。 ### onAllErrors接口与onerror接口之间的行为差异 1. 异常捕获范围 - onAllErrors接口可以捕获Worker线程的onmessage回调、timer回调以及文件执行等流程产生的全局异常。 + onAllErrors接口可以捕获Worker线程的onmessage回调、timer回调以及文件执行等流程中产生的全局异常。 onerror接口仅能捕获Worker线程的onmessage回调中同步方法产生的异常,无法捕获多线程回调和模块化相关异常。 2. 异常捕获后的线程状态 - onAllErrors接口捕获异常后,Worker线程仍然存活并可以继续使用。这使得开发者可以在捕获异常后继续执行其他操作,而不必担心线程被终止。 + onAllErrors接口捕获异常后,Worker线程仍然存活并可以继续使用。这使开发者可以在捕获异常后执行其他操作,无需担心线程终止。 - onerror接口一旦捕获到异常,Worker线程会进入销毁流程,无法继续使用。这意味着在onerror触发后,Worker线程将被终止,后续操作将无法进行。 + onerror接口捕获异常后,Worker线程会进入销毁流程,无法继续使用。这意味着在onerror触发后,Worker线程将被终止,后续操作将无法进行。 3. 适用场景 @@ -189,7 +189,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke 1. DevEco Studio支持一键生成Worker,在对应的{moduleName}目录下任意位置,单击鼠标右键 > New > Worker,即可自动生成Worker的模板文件及配置信息。本文以创建“worker”为例。 - 此外,支持手动创建Worker文件,具体方式和注意事项请参阅[创建Worker的注意事项](#创建worker的注意事项)。 + 支持手动创建Worker文件,具体方式和注意事项请参阅[创建Worker的注意事项](#创建worker的注意事项)。 2. 导入Worker模块。 @@ -198,7 +198,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke import { ErrorEvent, MessageEvents, worker } from '@kit.ArkTS' ``` -3. 在宿主线程中通过调用ThreadWorker的[constructor()](../reference/apis-arkts/js-apis-worker.md#constructor9)方法创建Worker对象,并注册回调函数。 +3. 在宿主线程中,通过调用ThreadWorker的[constructor()](../reference/apis-arkts/js-apis-worker.md#constructor9)方法创建Worker对象,并注册回调函数。 ```ts // Index.ets @@ -221,13 +221,13 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke // 创建Worker对象 let workerInstance = new worker.ThreadWorker('entry/ets/workers/worker.ets'); - // 注册onmessage回调,当宿主线程接收到来自其创建的Worker通过workerPort.postMessage接口发送的消息时被调用,在宿主线程执行 + // 注册onmessage回调,捕获宿主线程接收到来自其创建的Worker通过workerPort.postMessage接口发送的消息。该回调在宿主线程执行 workerInstance.onmessage = (e: MessageEvents) => { let data: string = e.data; console.info('workerInstance onmessage is: ', data); } - // 注册onAllErrors回调,可以捕获Worker线程的onmessage回调、timer回调以及文件执行等流程产生的全局异常,在宿主线程执行 + // 注册onAllErrors回调,捕获Worker线程的onmessage回调、timer回调以及文件执行等流程产生的全局异常。该回调在宿主线程执行 workerInstance.onAllErrors = (err: ErrorEvent) => { console.error('workerInstance onAllErrors message is: ' + err.message); } @@ -239,7 +239,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke // 注册onexit回调,当Worker销毁时被调用,在宿主线程执行 workerInstance.onexit = (e: number) => { - // 如果Worker正常退出,code为0;如果异常退出,code为1 + // Worker正常退出时,code为0;异常退出时,code为1 console.info('workerInstance onexit code is: ', e); } @@ -276,7 +276,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke console.error('workerPort onmessageerror'); } - // 注册onerror回调,当Worker在执行过程中发生异常被调用,在Worker线程执行 + // 注册onerror回调,捕获Worker在执行过程中发生的异常,在Worker线程执行 workerPort.onerror = (err: ErrorEvent) => { console.error('workerPort onerror err is: ', err.message); } @@ -286,9 +286,9 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke ## 跨har包加载Worker -1. 创建har详情参考[开发静态共享包](../quick-start/har-package.md)。 +1. 创建HAR详情参考[开发静态共享包](../quick-start/har-package.md)。 -2. 在har中创建Worker线程文件相关内容。 +2. 在HAR中创建Worker线程文件相关内容。 ```ts // worker.ets @@ -299,7 +299,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke ``` -3. 在entry模块的oh-package.json5文件中配置har包的依赖。 +3. 在entry模块的oh-package.json5文件中配置HAR包的依赖。 ```ts // 在entry模块配置har包的依赖 @@ -317,7 +317,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke ``` -4. 在entry模块中加载har包中的Worker线程文件。 +4. 在entry模块中加载HAR包中的Worker线程文件。 ```ts // Index.ets @@ -356,7 +356,7 @@ const workerFA3: worker.ThreadWorker = new worker.ThreadWorker('ThreadFile/worke ## 多级Worker生命周期管理 -支持创建多级Worker,即父Worker可以创建子Worker,形成层级线程关系。由于Worker线程的生命周期由开发者自行管理,因此需要正确管理多级Worker的生命周期。如果销毁父Worker时未能终止其子Worker的运行,可能会导致不可预期的结果。因此需确保子Worker的生命周期在父Worker生命周期范围内,销毁父Worker前,先销毁所有子Worker。 +支持创建多级Worker,即父Worker可以创建子Worker,形成层级线程关系。由于Worker线程的生命周期由开发者管理,因此需要正确管理多级Worker的生命周期。当销毁父Worker时未能终止其子Worker的运行,可能会导致不可预期的结果。所以需要确保子Worker的生命周期在父Worker生命周期范围内,销毁父Worker前,先销毁所有子Worker,以避免不可预期的结果。 ### 推荐使用示例 @@ -439,7 +439,7 @@ workerPort.onmessage = (e: MessageEvents) => { ### 不推荐使用示例 -不建议在父Worker销毁后,子Worker仍向父Worker发送消息。 +不建议在父Worker销毁后,子Worker继续向父Worker发送消息。 ```ts // main thread @@ -513,7 +513,7 @@ workerPort.onmessage = (e: MessageEvents) => { ``` -不建议在父Worker发起销毁操作的执行阶段创建子Worker。在创建子Worker线程之前,需确保父Worker线程始终处于存活状态,不建议在不确定父Worker是否发起销毁操作的情况下创建子Worker。 +不建议在父Worker发起销毁操作的执行阶段创建子Worker。在创建子Worker线程之前,需确保父Worker线程始终处于存活状态,建议在确定父Worker未发起销毁操作的情况下创建子Worker。 ```ts // main thread