鸿蒙开发之TaskPool的async函数如何返回值

背景

在鸿蒙的线程架构里面,主要分为:ArkTs线程(主线程)、TaskPool(线程池)、worker(子线程),ets/ts设计上,不同的线程之间不可能通过静态变量读取到对应的值,就是相当于Android的主内存和工作内存的概念是不存在鸿蒙系统上的,所以在ets上多线程就不会存在数据不同步等问题。
业务上我需要定时开启心跳请求保持通道连接不断,为了减少ArkTs线程的压力,我创建个子线程来发起网络请求,返回我又希望把子线程里面的网络请求结果返回给我的ArkTs线程,这时候就需要用到async/await 来搭配使用

注意:如果希望能多线程读取到正确的变量值,现在做法都是下沉到C++去保存状态了,这里提供了思路不过多具体描述。

TaskPool 介绍

  1. 鸿蒙提供的TaskPool可以为你创建子线程,子线程操作耗时的操作,然后返回结果到ArkTs线程。(这里返回到ArkTs线程的前提是你taskpool.execute是在ArkTs线程执行,如果你在其他线程C执行,那么execute的结果是返回线程C进行结果处理)。

  2. 鸿蒙使用线程池主要有下面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}}`)
        })

总结

  1. 如果想要理解鸿蒙系统原理,还是要下载相关源码看C++
  2. 子线程切换ArkTs线程都是用uv_work处理,官方uv_queue_work介绍
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容