【HarmonyOS NEXT】多线程并发-Worker

一、背景

在鸿蒙开发中提供了两种多线程并发方案,分别是TaskPool与Worker,此篇文章主要总结下Worker

二、Worker概念

1、Worker为应用程序提供一个多线程的运行环境,实现后台线程与宿主线程分离

2、Worker有自己的生命周期,一旦创建不会主动销毁,需手动销毁空闲的Worker

3、作用:在后台线程中处理耗时操作(如:计算密集型或高延迟任务),避免影响主线程(如:UI主线程)

4、目标:将「重量级、长期、有状态」的耗时逻辑从主线程剥离,解决主线程被阻塞导致 UI 无响应的问题

5、运作机制

Worker子线程和宿主线程通过消息传递机制通信,利用序列化、引用传递或转移所有权的机制完成命令和数据的交互

三、注意事项

1、创建Worker

A、自动创建:使用DevEco Studio 单击鼠标右键 > New > Worker,一键生成Worker的模板文件及配置信息

B、手动创建:在工程目录下创建Worker文件,并在build-profile.json5配置Worker文件路径

TypeScript 复制代码
//Stage模型:
"buildOption": {
  "sourceOption": {
    "workers": [
      "./src/main/ets/workers/worker.ets"
    ]
  }
}

2、文件路径

A、Stage模型--->路径规则:{moduleName}/ets/{relativePath}

TypeScript 复制代码
1. // worker线程文件所在路径:"entry/src/main/ets/workers/worker.ets"
2. const workerStage1: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/worker.ets');

B、HAR包中加载Worker线程文件--->路径规则:@{moduleName}/ets/{relativePath}

TypeScript 复制代码
1. // @标识路径加载形式:
2. // worker线程文件所在路径: "har/src/main/ets/workers/worker.ets"
3. const workerStage4: worker.ThreadWorker = new worker.ThreadWorker('@har/ets/workers/worker.ets');

3、资源加载

A、同时运行的Worker子线程数量最多为64个(与napi_create_ark_runtime创建的runtime总数不超过80)

B、单次序列化传输的数据量大小限制为16MB

4、模块使用限制

A、只能使用线程安全的库,UI相关的非线程安全库不能使用

B、不支持在多个HAP之间共享使用相同的Worker线程文件

C、不支持在Worker工作线程中AppStorage

D、禁止使用export语法导出

5、异常处理

A、API 18+使用onAllErrors回调捕获异常,Worker线程继续存活

B、API 18以前使用onerror回调捕获异常,Worker线程进入销毁流程,无法继续使用

四、Worker生命周期

生命周期顺序:创建--->运行--->销毁

1、创建阶段

在主线程或父Worker线程中,调用new worker.ThreadWorker(scriptURL)

2、运行阶段

通过 postMessage 和 onmessage 与创建它的线程进行双向通信。

  • 核心方法:

    • parentPort.postMessage(): 发送消息。

    • parentPort.onmessage(): 接收消息。

    • onerror(): 处理错误。

3、销毁阶段

由创建该Worker的线程(父线程)主动调用 worker.terminate()

  • terminate():立即终止

  • close():正常关闭

**关键点:**必须手动触发。对于多级Worker,必须严格遵循 "从子到父"的销毁顺序(即先销毁所有子Worker,再销毁父Worker)

五、怎么用

步骤1:配置构建文件

这一步是保证系统能找到新建的Worker脚本

打开 entry/build-profile.json5 文件,在 buildOption 字段内添加 sourceOption 配置:

步骤2:创建Worker后台脚本

在 entry/src/main/ets/ 目录下,创建 workers 文件夹并创建脚本文件

TypeScript 复制代码
import { MessageEvents, worker,ErrorEvent } from '@kit.ArkTS';

// 1. 获取通信端口
const parentPort = worker.workerPort;

// 2. 监听主线程发来的消息 - 使用正确的MessageEvent类型
parentPort.onmessage = (e: MessageEvents) => {
  console.log('[Worker] 收到数据: ' + e.data);

  // 3. 执行耗时计算 (例如计算斐波那契数列)
  const n: number = e.data;
  const result = fibonacci(n);

  // 4. 将结果发送回主线程
  console.log('[Worker] 计算完成,结果: ' + result);
  parentPort.postMessage(result);
};

// 一个模拟的耗时计算函数
function fibonacci(n: number): number {
  if (n <= 1) return n;
  // 注意:递归版本对较大n值会很慢,这里为演示用
  return fibonacci(n - 1) + fibonacci(n - 2);
}

// 5. 使用正确的ErrorEvent类型处理错误
parentPort.onerror = (ev: ErrorEvent): void => {
  console.error('[Worker] 发生错误: ' + ev.message);
};

步骤3:创建主页面调用Worker

TypeScript 复制代码
import { ErrorEvent, MessageEvents, worker } from '@kit.ArkTS';

@Entry
@Component
struct Index {
  @State result: string = '等待计算';
  @State isCalculating: boolean = false;
  private calcWorker?: worker.ThreadWorker

  build() {
    Column({ space: 20 }) {
      Text('Worker演示')
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 30 })

      Text(this.result)
        .fontSize(24)
        .fontColor(this.isCalculating ? Color.Red : Color.Black)
        .margin({ bottom: 20 })

      Button(this.isCalculating ? '计算中...' : '开始计算')
        .width('80%')
        .height(50)
        .fontSize(18)
        .backgroundColor(this.isCalculating ? Color.Gray : Color.Blue)
        .enabled(!this.isCalculating)
        .onClick(() => {
          this.startCalculation();
        })

      Button('终止Worker')
        .width('80%')
        .height(50)
        .fontSize(18)
        .backgroundColor(Color.Orange)
        .onClick(() => {
          this.terminateWorker();
        })

      // 显示进度或状态
      if (this.isCalculating) {
        LoadingProgress()
          .width(50)
          .height(50)
          .margin({ top: 20 })
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .padding(20)
  }

  // 启动Worker计算
  startCalculation() {
    // 1. 先清理可能存在的旧Worker
    this.terminateWorker();

    // 2. 更新UI状态
    this.isCalculating = true;
    this.result = '正在创建Worker...';
    console.log('[UI] 开始计算流程');

    try {
      // 3. 创建Worker实例
      this.calcWorker = new worker.ThreadWorker('entry/ets/worker/DataSyncWorker.ets');
      console.log('[UI] Worker创建成功');

      // 4. 设置Worker回调
      this.calcWorker.onmessage = (e: MessageEvents): void => {
        console.log('[UI] 收到Worker结果: ' + e.data);
        this.result = '计算结果: ' + e.data;
        this.isCalculating = false;

        // 计算完成后可以立即销毁Worker,或者保留以备后用
        this.terminateWorker();
      };

      this.calcWorker.onerror = (ev: ErrorEvent): void => {
        console.error('[UI] Worker发生错误: ' + ev.message);
        this.result = '错误: ' + ev.message;
        this.isCalculating = false;
      };


      // 5. 更新状态并发送计算任务
      this.result = '计算中...';
      console.log('[UI] 向Worker发送计算任务');

      // 计算斐波那契数列第30项(比35项快,适合演示)
      const calculateTarget = 30;
      this.calcWorker.postMessage(calculateTarget);

    } catch (error) {
      console.log('lucy== error',JSON.stringify(error))
      console.error('[UI] 创建Worker失败: ' + error.message);
      this.result = '创建Worker失败';
      this.isCalculating = false;
    }
  }

  // 终止Worker
  terminateWorker() {
    if (this.calcWorker) {
      try {
        this.calcWorker.terminate(); // 直接终止Worker,释放资源
        console.log('lucy== 终止成功')
        console.log('[UI] Worker已成功终止');
      } catch (err) {
        console.log('lucy== 终止失败',JSON.stringify(err))
        console.error('[UI] 终止Worker失败: ' + JSON.stringify(err));
      }
      this.calcWorker = undefined; // 清空实例引用,避免内存泄漏和误操作
    }
  }

  // 页面生命周期:离开时清理Worker
  aboutToDisappear(): void {
    console.log('[UI] 页面即将销毁,清理Worker');
    this.terminateWorker();
  }
}

六、适用场景

A、长耗时任务:执行时间 > 10秒(如大插件解压)

B、长期运行的后台服务(如音乐播放器、实时定位追踪)

C、频繁双向通信(如实时聊天的消息处理)

D、需指定专属线程(避免切换、绑定特性)

相关推荐
一起养小猫1 小时前
Flutter for OpenHarmony 实战:打造天气预报应用
开发语言·网络·jvm·数据库·flutter·harmonyos
小白郭莫搞科技6 小时前
鸿蒙跨端框架Flutter学习:CustomTween自定义Tween详解
学习·flutter·harmonyos
mocoding7 小时前
使用鸿蒙化flutter_fluttertoast替换Flutter原有的SnackBar提示弹窗
flutter·华为·harmonyos
2601_9495936510 小时前
高级进阶React Native 鸿蒙跨平台开发:LinearGradient 背景渐变与主题切换
react native·react.js·harmonyos
深海呐10 小时前
鸿蒙基本UI控件(List相关-含Grid)
harmonyos·harmonyos ui·harmonyos list·harmonyos grid·鸿蒙列表view·art列表ui控件·art网格ui控件
小雨青年10 小时前
鸿蒙 HarmonyOS 6 | AI Kit 集成 Core Speech Kit 语音服务
人工智能·华为·harmonyos
一起养小猫11 小时前
Flutter for OpenHarmony 实战 表单处理与验证完整指南
android·开发语言·前端·javascript·flutter·harmonyos
摘星编程12 小时前
React Native鸿蒙版:自定义useMask输入掩码
react native·react.js·harmonyos
mocoding12 小时前
使用Flutter设置UI三方库card_settings_ui重构鸿蒙版天气预报我的页面
flutter·ui·harmonyos
摘星编程13 小时前
OpenHarmony + RN:自定义useValidator表单验证
react native·react.js·harmonyos