OpenHarmony Stage Worker 多线程

系统 OpenHarmony
在实际开发项目经常遇到网络请求、文件读写、大图片加载等相对耗时的操作,如果这些耗时操作都在主线程中处理,就会导致应用UI界面被卡住,无法操作。

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

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

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

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

社区介绍:​​Worker​

开发环境

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

效果

​视频地址​

OpenHarmony stage worker 多线程-开源基础软件社区

开发与调试

社区提供了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

@ohos.​​worker​​@ohos.file.fs 暂时没有,但是可以参看: @ohos.fileio
@ohos.promptAction

项目结构

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

OpenHarmony stage worker 多线程-开源基础软件社区

关键代码

创建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)这里需要理解下Stage模型中worker.ThreadWorker接口参数scriptURL=“entry/ets/worker/worker.ts”:

entry: 为module.json5文件中module的name属性对应的值;
ets: 表明当前使用的语言。

OpenHarmony stage worker 多线程-开源基础软件社区

(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"
]
}
}

OpenHarmony stage worker 多线程-开源基础软件社区

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子线程处理耗时操作任务。

责任编辑:jianghua 来源: 51CTO 开源基础软件社区
相关推荐

2023-08-01 16:35:48

鸿蒙ArkUI应用开发

2009-03-12 10:52:43

Java线程多线程

2024-08-05 00:04:00

JSWeb应用

2023-06-05 07:56:10

线程分配处理器

2023-06-06 08:17:52

多线程编程Thread类

2013-07-16 10:12:14

iOS多线程多线程概念多线程入门

2021-12-26 18:22:30

Java线程多线程

2009-06-29 17:49:47

Java多线程

2010-01-21 11:27:30

linux多线程机制线程同步

2023-06-13 13:39:00

多线程异步编程

2011-07-21 11:12:58

iPhone 线程 多线程

2020-12-28 08:03:26

多线程进程浏览器

2011-06-02 17:27:49

iphone 多线程

2021-06-11 11:28:22

多线程fork单线程

2023-06-07 13:49:00

多线程编程C#

2010-03-15 17:56:23

Java多线程

2021-03-05 07:38:52

C++线程编程开发技术

2022-04-14 11:44:25

LiteOS线程鸿蒙

2009-08-17 16:56:51

C#多线程控制进度条

2020-09-08 10:56:55

Java多线程存储器
点赞
收藏

51CTO技术栈公众号