【关键字】
全局常驻任务 / @ohos.taskpool(启动任务池)/ @ohos.worker(启动一个Worker)/ Sendable装饰器 / AudioRenderer
【问题描述】
针对一个全局常驻任务解决方案,遇到下面几个问题:
-
问题一:使用如下最小单元demo代码,测试时发现,setTimeout最小设置为1,如果小于1会阻塞UI,有优化这种实现方式的方法吗?
@Entry @Component struct Index { @State message:string = '点击’; aboutToAppear(): void { // this.testTask() this.testTask1() } async testTask() { // 此场景不会阻塞app页面加载. 但是内存会持续增长 while (true) { await new Promise<void>((resolve, rej) => setTimeout(()=> { resolve(); }, 1)); } } async testTask1() { // 此场景异常, 阻塞页面加载, 内存持续增长 while (true) { await new Promise<void>((resolve, rej) => setTimeout(()=> { resolve(); }, 0.1)); } }
-
问题二:taskpool不支持非序列化对象,如果使用taskpool实现常驻任务,并且回调自定义对象或者UI页面进行业务处理,可以怎么处理,有没有好的解决方案或者简易demo?
-
问题三:若通过taskpool实现多线程,如何传递自定义Class对象?代码如下,按照文档不支持非序列话对象。是否有方案在readAudioData的循环中获取audioCapturer对象用于读取数据?
class AudioManager { audioCaptrue?: audio.AudioCapturer } @Concurrent function readAudioData(audioManager: AudioManager) { while (true) { // 业务处理 audioManager.audioCaptrue } }
-
问题四:Sendable装饰器支持SendableClass序列化, 但是如何在taskpool或者worker线程中访问系统定义的对象数据,例如AudioRenderer音频录制对象。它看起来不是一个Class,而是一个接口类型,这种应该怎么处理?
【解决方案】
-
问题一:现在定时器的精度是ms级的,如果小于1,就会设置成0, 因为这个原因所以会阻塞UI。
-
问题二:taskpool当前还不支持长时任务,常驻任务建议使用worker。如果一定要使用taskpool,涉及UI时需要考虑线程安全的问题。
@ohos.worker接口文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-worker-0000001860176065
多线程安全注意事项,请参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/multi-thread-safety-0000001774279778
-
问题三:可使用Sendable装饰Class,Sendable装饰器支持SendableClass序列化。对象分配在各自的虚拟机内存空间,不存在竞争访问,不同线程可以同时读写。
Sendable开发指导:https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/arkts-utils/arkts-sendable.md
-
问题四:AudioRenderer是系统接口,可以正常使用,不需要装饰器。