1e41f4b71Sopenharmony_ci# ArrayBuffer对象
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ciArrayBuffer内部包含一块Native内存。其JS对象壳与普通对象一样,需要经过序列化与反序列化拷贝传递,但是Native内存有两种传输方式:拷贝和转移。
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci传输时采用拷贝的话,需要经过深拷贝(递归遍历),传输后两个线程都可以独立访问ArrayBuffer。通信过程如下图所示:
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci![copy_transfer](figures/copy_transfer.png)
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci如果采用转移的方式,则原线程无法使用此ArrayBuffer对象,跨线程时只需重建JS壳,Native内存无需拷贝,效率更高。通信过程如下图所示:
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci![transfer](figures/transfer.png)
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ciArrayBuffer可以用来表示图片等资源,在应用开发中,会遇到需要进行图片处理的场景(比如需要调整一张图片的亮度、饱和度、大小等),为了避免阻塞主线程,可以将图片传递到子线程中执行这些操作。转移方式性能更高,但是原线程不能再访问ArrayBuffer对象,如果两个线程都需要访问,则需要采用拷贝方式,否则建议采用转移方式,提升性能。
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci下面将分别通过拷贝和转移的方式,将图片传递到子线程中。
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci## ArrayBuffer拷贝传输方式
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci在ArkTS中,TaskPool传递ArrayBuffer数据时,默认使用转移的方式,通过调用setTransferList()接口,指定对应的部分数据传递方式为转移方式,其余部分数据可以切换成拷贝的方式。
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci首先,实现一个需要在Task中执行的用于处理ArrayBuffer的接口。
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci然后,通过拷贝的方式将ArrayBuffer数据传递到Task中,并在Task中处理ArrayBuffer。
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci最后,主线程接收到Task执行完毕后返回的ArrayBuffer数据,拼接数据展示。
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ci```ts
28e41f4b71Sopenharmony_ci// Index.ets
29e41f4b71Sopenharmony_ciimport { taskpool } from '@kit.ArkTS';
30e41f4b71Sopenharmony_ciimport { BusinessError } from '@kit.BasicServicesKit';
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ci@Concurrent
33e41f4b71Sopenharmony_cifunction adjustImageValue(arrayBuffer: ArrayBuffer): ArrayBuffer {
34e41f4b71Sopenharmony_ci  // 对arrayBuffer进行操作
35e41f4b71Sopenharmony_ci  return arrayBuffer;  // 返回值默认转移
36e41f4b71Sopenharmony_ci}
37e41f4b71Sopenharmony_ci
38e41f4b71Sopenharmony_cifunction createImageTask(arrayBuffer: ArrayBuffer, isParamsByTransfer: boolean): taskpool.Task {
39e41f4b71Sopenharmony_ci  let task: taskpool.Task = new taskpool.Task(adjustImageValue, arrayBuffer);
40e41f4b71Sopenharmony_ci  if (!isParamsByTransfer) { // 是否使用转移方式
41e41f4b71Sopenharmony_ci    // 传递空数组[],全部arrayBuffer参数传递均采用拷贝方式
42e41f4b71Sopenharmony_ci    task.setTransferList([]);
43e41f4b71Sopenharmony_ci  }
44e41f4b71Sopenharmony_ci  return task;
45e41f4b71Sopenharmony_ci}
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ci@Entry
48e41f4b71Sopenharmony_ci@Component
49e41f4b71Sopenharmony_cistruct Index {
50e41f4b71Sopenharmony_ci  @State message: string = 'Hello World';
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci  build() {
53e41f4b71Sopenharmony_ci    RelativeContainer() {
54e41f4b71Sopenharmony_ci      Text(this.message)
55e41f4b71Sopenharmony_ci        .id('HelloWorld')
56e41f4b71Sopenharmony_ci        .fontSize(50)
57e41f4b71Sopenharmony_ci        .fontWeight(FontWeight.Bold)
58e41f4b71Sopenharmony_ci        .alignRules({
59e41f4b71Sopenharmony_ci          center: { anchor: '__container__', align: VerticalAlign.Center },
60e41f4b71Sopenharmony_ci          middle: { anchor: '__container__', align: HorizontalAlign.Center }
61e41f4b71Sopenharmony_ci        })
62e41f4b71Sopenharmony_ci        .onClick(() => {
63e41f4b71Sopenharmony_ci          let taskNum = 4;
64e41f4b71Sopenharmony_ci          let arrayBuffer = new ArrayBuffer(1024 * 1024);
65e41f4b71Sopenharmony_ci          let taskPoolGroup = new taskpool.TaskGroup();
66e41f4b71Sopenharmony_ci          // 创建taskNum个Task
67e41f4b71Sopenharmony_ci          for (let i: number = 0; i < taskNum; i++) {
68e41f4b71Sopenharmony_ci            let arrayBufferSlice: ArrayBuffer = arrayBuffer.slice(arrayBuffer.byteLength / taskNum * i, arrayBuffer.byteLength / taskNum * (i + 1));
69e41f4b71Sopenharmony_ci            // 使用拷贝方式传入ArrayBuffer,所以isParamsByTransfer为false
70e41f4b71Sopenharmony_ci            taskPoolGroup.addTask(createImageTask(arrayBufferSlice, false));
71e41f4b71Sopenharmony_ci          }
72e41f4b71Sopenharmony_ci          // 执行Task
73e41f4b71Sopenharmony_ci          taskpool.execute(taskPoolGroup).then((data) => {
74e41f4b71Sopenharmony_ci            // 返回结果,对数组拼接,获得最终结果
75e41f4b71Sopenharmony_ci          }).catch((e: BusinessError) => {
76e41f4b71Sopenharmony_ci            console.error(e.message);
77e41f4b71Sopenharmony_ci          })
78e41f4b71Sopenharmony_ci        })
79e41f4b71Sopenharmony_ci    }
80e41f4b71Sopenharmony_ci    .height('100%')
81e41f4b71Sopenharmony_ci    .width('100%')
82e41f4b71Sopenharmony_ci  }
83e41f4b71Sopenharmony_ci}
84e41f4b71Sopenharmony_ci```
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci## ArrayBuffer转移传输方式
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ci在TaskPool中,传递ArrayBuffer数据,默认使用转移方式,原线程不能再使用传输给子线程的ArrayBuffer。所以在上文示例的基础上,去除task.setTransferList接口就可以实现,即createImageTask第二个参数传入true。
89