背景
在鸿蒙的线程架构里面,主要分为:ArkTs线程(主线程)、TaskPool(线程池)、worker(子线程),ets/ts设计上,不同的线程之间不可能通过静态变量读取到对应的值,就是相当于Android的主内存和工作内存的概念是不存在鸿蒙系统上的,所以在ets上多线程就不会存在数据不同步等问题。
业务上我需要定时开启心跳请求保持通道连接不断,为了减少ArkTs线程的压力,我创建个子线程来发起网络请求,返回我又希望把子线程里面的网络请求结果返回给我的ArkTs线程,这时候就需要用到async/await 来搭配使用
注意:如果希望能多线程读取到正确的变量值,现在做法都是下沉到C++去保存状态了,这里提供了思路不过多具体描述。
TaskPool 介绍
鸿蒙提供的TaskPool可以为你创建子线程,子线程操作耗时的操作,然后返回结果到ArkTs线程。(这里返回到ArkTs线程的前提是你taskpool.execute是在ArkTs线程执行,如果你在其他线程C执行,那么execute的结果是返回线程C进行结果处理)。
鸿蒙使用线程池主要有下面2种方法
//方法一,创建Task对象,然后把@Concurrent修饰的function传入,args是function接收的参数
let task = new Task(fuction, args);
taskpool.execute(task)
//方法二,把@Concurrent修饰的function传入,args是function接收的参数
taskpool.execute(fuction, args);
使用方面问题
假如我有个网络请求的request方法如下
//这个请求是网络接口的
function request(url: string, method: string) : Promise<HttpResponse>
错误版本代码调用
错误版本一:下面代码虽然没有编译错误,但是在execute后没有成功返回结果,只返回了错误消息
@Concurrent
async function TestTask(url: string, method:string): Promise<HttpResponse> {
let response: http.HttpResponse = await request(url, method)
return new Promise<HttpResponse>((resolve, reject) => {
resolve(response)
})
}
//then没有输出,输出了error,error信息告诉你不能return 一个 新的Promise,原因后面会讲解
taskpool.execute(TestTask).then((resp: HttpResponse) => {
console.log(TAG, `ping execute code${resp.code}}`)
}).catch((error: BusinessError) => {
console.log(TAG, `ping execute task error=${error}}`)
})
错误版本二:直接编译器报错, 告诉你async修饰的函数返回值必须是Promise
@Concurrent
async function TestTask(url: string, method:string): HttpResponse {
let response: http.HttpResponse = await request(url, method)
return response
}
原因
上面出错的原因主要是async修饰的函数,默认在底层C++已经给你创建一个关联起来的promise deffer了,如果你再创建一个新的进去,依赖关联不上,所以不支持你return new 新的Promise返回。错误版本二就更好理解了,因为底层已经创建了Promise deffer,直接限制你返回值必须是Promise<T>
正确用法
上面知道原因后大致聪明的你已经想到如何在async函数里面返回正确的值了。下面两种方法都是支持的
@Concurrent
async function TestTask(url: string, method:string): Promise<HttpResponse> {
let response: http.HttpResponse = await request(url, method)
return response
}
or
@Concurrent
async function TestTask(url: string, method:string) {
let response: http.HttpResponse = await request(url, method)
return response
}
//下面then就可以正常输出结果了
taskpool.execute(TestTask).then((resp: HttpResponse) => {
console.log(TAG, `ping execute code${resp.code}}`)
}).catch((error: BusinessError) => {
console.log(TAG, `ping execute task error=${error}}`)
})
总结
- 如果想要理解鸿蒙系统原理,还是要下载相关源码看C++
- 子线程切换ArkTs线程都是用uv_work处理,官方uv_queue_work介绍