【HarmonyOS】TaskPool非阻塞UI
【HarmonyOS】TaskPool方法不会阻塞UI,如果做上传图片的功能加载Loading记得使用TaskPool,Promise、Async/Await都会阻塞UI
【引言】
发现Promise可能会阻塞UI,尝试使用async或await,但发现它们仍然会导致阻塞。后来看到chaoxiaoshu回复的TaskPool方法,发现使用该方法后UI不再阻塞。因此,我特意编写了一个加载弹窗进行测试,结果同样显示,只有TaskPool方法不会阻塞UI。
【代码示例】
import { taskpool } from '@kit.ArkTS'; @Component export struct MyDialog_1 { @Prop dialogID: string @State title: string = '加载中...' build() { Stack() { Column() { LoadingProgress() .color(Color.White).width(100).height(100) Text(this.title) .fontSize(18).fontColor(0xffffff).margin({ top: 8 }) .visibility(this.title ? Visibility.Visible : Visibility.None) } } .onClick(() => { getContext(this).eventHub.emit(this.dialogID, "关闭弹窗") }) .width(180) .height(180) .backgroundColor(0x88000000) .borderRadius(10) .shadow({ radius: 10, color: Color.Gray, offsetX: 3, offsetY: 3 }) } } @Entry @Component struct Page28 { @State time3: string = "" @State isShowLoading: boolean = false build() { Stack() { Column({ space: 20 }) { Button("【方案一】测试Promise") .type(ButtonType.Capsule) .onClick(() => { this.isShowLoading = true this.time3 = 'loading...' console.log("start call promise") testPromise(100000000).then((time) => { this.time3 = `耗时:${time}` console.log("promise then") this.isShowLoading = false }) console.log("end call promise") }) Button("【方案二】测试async await") .type(ButtonType.Capsule) .onClick(() => { this.isShowLoading = true this.time3 = 'loading...' console.log("start call promise") this.testPromise() console.log("end call promise") }) Button("【方案三】测试taskpool") .type(ButtonType.Capsule) .onClick(() => { this.isShowLoading = true this.time3 = 'loading...' let task: taskpool.Task = new taskpool.Task(concurrentFunc, 100000000); taskpool.execute(task); task.onReceiveData((time: number) => { this.time3 = `耗时:${time}`; console.log("====end") this.isShowLoading = false }) }) Text(this.time3) }.alignItems(HorizontalAlign.Start) MyDialog_1().visibility(this.isShowLoading ? Visibility.Visible : Visibility.None) }.width('100%').height('100%') } //耗时操作 async testPromise() { let time = await testPromise(100000000) time = new Date().getTime() - time this.time3 = `耗时:${time}毫秒` console.log("promise then") this.isShowLoading = false } } function testPromise(count: number): Promise<number> { return new Promise<number>((resolve) => { let time = Date.now().valueOf() let num = 0 for (let i = 0; i < count; i++) { +num } time = Date.now().valueOf() - time resolve(time) }) } @Concurrent function concurrentFunc(count: number): void { let time = Date.now().valueOf() let num = 0 for (let i = 0; i < count; i++) { +num } time = Date.now().valueOf() - time taskpool.Task.sendData(time); }
【方案一:Promise】
优点:
易于理解:Promise的语法简单,易于理解和使用。
链式调用:可以通过.then进行链式调用,处理多个异步操作。
缺点:
阻塞UI:在执行耗时任务时,Promise会阻塞UI线程,导致Loading弹窗不能及时显示。
【方案二:Async/Await】
优点:
同步写法:Async/Await 使异步代码看起来像同步代码,更加直观。
错误处理:可以使用try/catch块处理错误,使代码更加清晰。
缺点:
阻塞UI:与Promise类似,Async/Await在执行耗时任务时仍会阻塞UI线程,导致Loading弹窗不能及时显示。
【方案三:TaskPool】
优点:
真正的异步:TaskPool可以将耗时任务放到独立的线程中执行,不会阻塞UI线程,保证了UI的流畅性。
数据通信:通过task.onReceiveData可以方便地接收任务结果。
缺点:
复杂度增加:引入了多线程处理,增加了代码的复杂度和维护成本。
【使用注意事项】
任务复杂度:
如果任务较为简单且不会长时间阻塞UI,可以考虑使用Promise或Async/Await。
如果任务较为复杂且耗时较长,建议使用TaskPool以保证UI的流畅性(例如,上传图片时显示加载中)。
代码可读性:
Promise和Async/Await的语法较为简单,适合初学者使用。
TaskPool需要对多线程有一定了解,适合有经验的开发者。
性能考虑:
TaskPool在处理大量或耗时任务时表现更优,可以显著提升应用性能。
Promise和Async/Await在小任务场景下更简洁高效。
【总结】
选择合适的异步操作方案至关重要。Promise和Async/Await适合处理简单的异步任务,而TaskPool则在处理复杂耗时任务时表现出色。根据实际需求,选择最适合的方案,能有效提升开发效率和用户体验。希望本文对您在异步操作的选择和使用上有所帮助。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了