OpenHarmony stage worker 多线程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenHarmony stage worker 多线程相关的知识,希望对你有一定的参考价值。

作者:徐金生

OpenHarmony存在一个与主线程并行的独立线程--Worker。对于处理耗时操作且不阻塞主线程起到了重要的作用,并且多个线程并发可以提高CPU和内存的利用率。在实际开发项目经常遇到网络请求、文件读写、大图片加载等相对耗时的操作,如果这些耗时操作都在主线程中处理,就会导致应用UI界面被卡住,无法操作。但需要注意的是:Worker线程中不能直接操作UI,需要通过消息通知UI线程进行更新。

社区介绍:Worker

开发环境

系统:OpenHarmony 3.2 beta4 开发板:DAYU200 SDK:API9 - FullSDK(3.2.9.2)

效果

视频地址

开发与调试

社区提供了Worker Demo,使用API8,FA模型,JS的方式实现,如果有兴趣可以参看:JsWorker

在API9的版本后,只能选用Stage模型开发,下面我们就介绍下基于API9、Stage模型开发Worker异步线程。

需求

首先我们先确认我们本次开发调试的内容 1、UI界面显示一行文本,用于显示操作流程,三个按钮:主线程保存数据、子线程保存数据、UI。

  • 主线程保存数据:UI线程向指定文件中写入1000000条数据;
  • 子线程保存数据:通知Worker线程向指定文件中写入1000000条数据;
  • UI:界面toast提示“click UI”,用于测试在不同线程中保存数据是否阻塞主线程操作。

2、在主线程中向指定文件写入数据,写入完成后Toast提示:“数据保存成功”;

3、在子线程中向指定文件写入数据,写入完成后Toast提示:“数据保存成功”;

4、在执行2、3时,点击UI按钮,查看操作结果。

涉及到的API

项目结构

在介绍相关代码之前,我们先看下API9 stage模型下的项目目录结构:

关键代码

创建Worker子线程,需要构造ThreadWorker实例,通过ThreadWorker实例属性onmessage监听Worker发送给宿主线程的消息。

1、ThreadWorker

参数:

参数名 类型 必填 说明
scriptURL string Worker执行脚本的路径。<br/>在FA和Stage模型下,DevEco Studio新建Worker工程路径分别存在以下两种情况:<br/>(a) worker脚本所在目录与pages目录同级。<br/>(b) worker脚本所在目录与pages目录不同级。
options WorkerOptions Worker构造的选项。

返回值:

类型 说明
ThreadWorker 执行ThreadWorker构造函数生成的ThreadWorker对象,失败则返回undefined。

代码:index.ets

import worker from @ohos.worker;


private workerInstance: worker.ThreadWorkerprivate readonly scriptURL: string = entry/ets/worker/worker.ts

aboutToAppear() 
    //  主线程中创建Worker对象
    this.workerInstance = new worker.ThreadWorker(this.scriptURL, 
      name: worker_thread
    )
    // 注册监听器
    // 具体宿主线程发送的信息
    this.workerInstance.onmessage = function(e)
      let data = e.data
      console.info(`$TAG workerInstance.onmessage $data`)
      this.result = data
      this.showSaveToast()
    .bind(this)
    this.workerInstance.onexit = function () 
      console.info(`$TAG  workerInstance onexit`)
    
  
  
  showSaveToast() 
  // 数据保存成功
  promptAction.showToast(
    message: 数据保存成功,
    duration: 2000
  )


1.1、这里需要理解下Stage模型中worker.ThreadWorker接口参数scriptURL="entry/ets/worker/worker.ts":

1.2、主线程与Worker线程间支持的数据类型参考序列化支持类型

2、worker/worker.ts

worker.ts脚本通过@ohos.worker.workerPort获取到ThreadWorkerGlobalScope对象,主要用于Worker线程与宿主线程通信,可以通过postMessage接口发送消息给宿主线程。

  • onMessage:表示Worker线程收到来自其宿主线程通过postMessage接口发送的消息时被调用的事件处理程序,处理程序在Worker线程中执行;
  • onMessageerror:表示当Worker对象接收到一条无法被反序列化的消息时被调用的事件处理程序,处理程序在Worker线程中执行。

worker.ts代码


import worker from @ohos.worker;
import  MyMessage  from ../modele/MyMessage
import  MessageType  from ../modele/MessageType
import fileIo from @ohos.file.fs
const TAG: string = [worker]
// 创建worker线程中与主线程通信的对象
const workerPort = worker.workerPort
let fd: number = 0
// worker线程接收主线程信息
workerPort.onmessage = function (e) 
    // data:主线程发送的消息
    let data = e.data as MyMessage
    console.info(`$TAG workerPort.onmessage $e`)
    let type = data.type
    switch (type) 
        case MessageType.CLOSE: 
            // 关闭线程
            console.info(`$TAG workerPort.onmessage close`)
            workerPort.close()
            break
        
        case MessageType.SAVE: 
            console.info(`$TAG workerPort.onmessage save path: $data.path`)
            if (data.path) 
                // 保存数据到文件
                if (fd <= 0) 
                    fd = fileIo.openSync(data.path, 0o2 | 0o100).fd
                
                for (var index = 0; index < 1000000; index++) 
                    fileIo.writeSync(fd, Worker Thread  + data.data +  + index +  \\n)
                
            
            // 向主线程发送消息
            workerPort.postMessage(data.data +  数据保存完成)
            break
        
        default: 
            console.error(`$TAG workerPort.onmessage message type error`)
        
    

// worker线程发生error的回调
workerPort.onerror = function (e) 
    console.info(`$TAG workerPort.onerror $JSON.stringify(e)`)

3、更新UI界面

通过worker.workerPort.postMessage()向宿主线程发送消息,宿主线程的worker.ThreadWorker().onMessage()收到消息后,toast提示:“数据保存成功”更新UI。此处代码在上述1、ThreadWorker 和 2、worker/worker.ts 中都有体现。

4、添加配置

在工程的模块级build-profile.json文件的buildOption属性中添加配置信息。

"buildOption": 
    "sourceOption": 
      "workers": [
        "./src/main/ets/worker/worker.ts"
      ]
    
  

5、界面布局

  build() 
    Column() 
      Text(this.result)
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
      Button(主线程保存数据)
        .width(50%)
        .height(50)
        .fontSize(24)
        .margin(
          top: 20,
          bottom: 20
        )
        .onClick(() => 
          this.showStartSaveToast()
          this.result = worker test..
          let fd = fileIo.openSync(globalThis.getContext(this).filesDir + / + catch_log.txt, 0o2 | 0o100).fd
          for (var index = 0; index < 1000000; index++) 
            fileIo.writeSync(fd, UI Thread This write data + index +  \\n)
          
          this.result = worker test success
          this.showSaveToast()
        )
      Button(子线程保存数据)
        .width(50%)
        .height(50)
        .fontSize(24)
        .margin(
          top: 20,
          bottom: 20
        )
        .onClick(() => 
          this.showStartSaveToast()
          this.result = worker test..
          let oldData = This write data
          let sendData: MyMessage = new MyMessage()
          sendData.type = MessageType.SAVE
          sendData.path = globalThis.getContext(this).filesDir + / + catch_log.txt
          sendData.data = oldData
          this.sendMessage(sendData)
        )
      Button(UI)
        .width(50%)
        .height(50)
        .fontSize(24)
        .margin(
          top: 20,
          bottom: 20
        )
        .onClick(() => 
          promptAction.showToast(
            message: click UI,
            duration: 3000
          )
        )
    
    .width(100%)
    .height(100%)
  

到此完成的Worker子线程处理耗时操作任务。

完整代码

EtsWorker

感谢

如果您能看到最后,还希望您能动动手指点个赞,一个人能走多远关键在于与谁同行,我用跨越山海的一路相伴,希望得到您的点赞。

本文作者:NL_AIDC_XJS

想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​

以上是关于OpenHarmony stage worker 多线程的主要内容,如果未能解决你的问题,请参考以下文章

#打卡不停更#FFH浅析Ability框架中Stage模型与FA模型的差异

spark2

Flink工作原理

Spark Core 1.3.1源码解析及个人总结

OpenHarmony内核学习[1]--单独编译OpenHarmony标准系统内核

OpenHarmony轻量系统开发初始OpenHarmony