1e41f4b71Sopenharmony_ci# ArrayBuffer对象 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ciArrayBuffer内部包含一块Native内存。其JS对象壳与普通对象一样,需要经过序列化与反序列化拷贝传递,但是Native内存有两种传输方式:拷贝和转移。 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci传输时采用拷贝的话,需要经过深拷贝(递归遍历),传输后两个线程都可以独立访问ArrayBuffer。通信过程如下图所示: 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci如果采用转移的方式,则原线程无法使用此ArrayBuffer对象,跨线程时只需重建JS壳,Native内存无需拷贝,效率更高。通信过程如下图所示: 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci 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