HarmonyOS 鸿蒙Next中taskpool任务依赖和promise回调时序

HarmonyOS 鸿蒙Next中taskpool任务依赖和promise回调时序

taskpool是否保证上一个依赖task的所有回调执行完,才执行依赖链下一个task

这里task1依赖task2,task2依赖task3,假如task2的执行需要task1的.then或者.catch内的执行结果,能否保证执行task2的时间在完成task1的.then之后

@Concurrent
function delay(args: number): number {
  let t: number = Date.now();
  while ((Date.now() - t) < 1000) {
	continue;
  }
  return args;
}

let task1:taskpool.Task = new taskpool.Task(delay, 100);
let task2:taskpool.Task = new taskpool.Task(delay, 200);
let task3:taskpool.Task = new taskpool.Task(delay, 200);

console.info("dependency: add dependency start");
task1.addDependency(task2);
task2.addDependency(task3);
console.info("dependency: add dependency end");

console.info("dependency: start execute")
taskpool.execute(task1).then(() => {
  console.info("dependency: task1 success");
})
taskpool.execute(task2).then(() => {
  console.info("dependency: task2 success");
})
taskpool.execute(task3).then(() => {
  console.info("dependency: task3 success");
})

更多关于HarmonyOS 鸿蒙Next中taskpool任务依赖和promise回调时序的实战教程也可以访问 https://www.itying.com/category-93-b0.html

7 回复

【背景知识】

  • TaskPool为应用程序提供多线程环境,降低资源消耗、提高系统性能,无需管理线程生命周期。TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择合适的工作线程执行任务,再将结果返回给宿主线程。接口易用,支持任务执行、取消和指定优先级,同时通过系统统一线程管理,结合动态调度及负载均衡算法,可以节约系统资源。
  • addDependency表示当前任务添加对其他任务的依赖。使用该方法前需先构造Task。该任务和被依赖的任务不能是任务组任务、串行队列任务、异步队列任务、已执行任务或周期任务。存在依赖关系的任务(依赖其他任务的任务或被依赖的任务)执行后不可再次执行。

【解决方案】

定义3个任务task1、task2、task3,依赖关系为task3->task2->task1;为了保证执行顺序为task3->task2->task1;使用addDependency接口建立各个任务之间的依赖关系达到任务的顺利执行。方案具体代码实现:

import { taskpool } from '@kit.ArkTS';

@Component
@Entry
struct TaskPoolDemo {
  build() {
    Column() {
      Text('TaskTool多任务顺序执行')
    }
  }

  aboutToAppear(): void {
    let task1: taskpool.Task = new taskpool.Task(delay, 100);
    let task2: taskpool.Task = new taskpool.Task(delay, 200);
    let task3: taskpool.Task = new taskpool.Task(delay, 200);

    console.info("dependency: add dependency start");
    task1.addDependency(task2);
    task2.addDependency(task3);
    console.info("dependency: add dependency end");

    console.info("dependency: start execute second");
    taskpool.execute(task1).then(() => {
      console.info("dependency: second task1 success");
    })
    taskpool.execute(task2).then(() => {
      console.info("dependency: second task2 success");
    })
    taskpool.execute(task3).then(() => {
      console.info("dependency: second task3 success");
    })
  }
}

@Concurrent
function delay(args: number): number {
  let t: number = Date.now();
  while ((Date.now() - t) < 1000) {
    continue;
  }
  return args;
}

打印日志如下:

06-23 17:34:24.694         dependency: add dependency start
06-23 17:34:24.694         dependency: add dependency end
06-23 17:34:24.694         dependency: start execute second
06-23 17:34:25.990         dependency: second task3 success
06-23 17:34:26.990         dependency: second task2 success
06-23 17:34:27.991         dependency: second task1 success

更多关于HarmonyOS 鸿蒙Next中taskpool任务依赖和promise回调时序的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


你好,我其实想确认的是:依赖关系为task3->task2->task1,那么task2是在task3本身完成之后就可能开始执行,还是在task3的.then也全部完成之后才会开始执行,这种执行关系是有保证的吗。

从日志打印上就可以看出执行顺序:task3->task2->task1;每个task都是等then中回调函数执行完成,

2个问题:

其一: 通过addDependency建立的依赖仅控制任务本体的执行顺序。你的示例中:

  • task3 → task2 → task1 的执行顺序由依赖关系保证
  • 每个任务的execute()方法会等待其所有依赖任务完成主逻辑后才会执行

代码执行顺序问题:

// 示例中三个任务实际执行顺序应为:task3 → task2 → task1
// 但代码中并行调用execute会导致依赖链失效
taskpool.execute(task1)  // 应最后执行
taskpool.execute(task2)  // 应第二个执行
taskpool.execute(task3)  // 应第一个执行

正确的写法应为顺序提交任务:

taskpool.execute(task3).then(() => {
    taskpool.execute(task2).then(() => {
        taskpool.execute(task1)
    })
})

其二: 回调执行机制:

  • .then/.catch回调属于微任务,会在主任务完成后按事件循环机制执行
  • 不保证在下一个依赖任务开始前完成

时序对比场景:

// 若task2需要task1的then回调结果
taskpool.execute(task1).then((result) => {
    const modifiedResult = process(result) // 回调处理
    // 此处需要显式触发task2执行
    taskpool.execute(task2) 
})

解决方案

// 正确方式:通过Promise链管理
taskpool.execute(task3)
    .then(() => taskpool.execute(task2))
    .then(() => taskpool.execute(task1))
    .then(() => { /* 处理最终结果 */ })

验证

  1. 日志验证:
taskpool.execute(task3).then(() => {
    console.log("task3完成时间戳:", Date.now())
})
taskpool.execute(task2).then(() => {
    console.log("task2完成时间戳:", Date.now())
})
// 若两个时间戳接近或重叠,说明并行执行
  1. 线程ID检查:
@Concurrent
function logThreadId(args: number): number {
    console.log("执行线程ID:", process.tid)
    return args
}
// 通过观察输出可验证任务是否按预期顺序执行

您好,可以看一下以下两个方案:

  1. TaskGroup的相关介绍和使用:使用TaskPool执行多个耗时任务-线程间通信场景-并发线程间通信-ArkTS并发-ArkTS(方舟编程语言)-应用框架 - 华为HarmonyOS开发者

多个任务同时执行时,由于任务复杂度不同,执行时间和返回数据的时间也会不同。如果宿主线程需要所有任务执行完毕的数据,可以通过TaskGroup的方式实现。

  1. 同步任务

同步任务是指在多个线程之间协调执行的任务,其目的是确保多个任务按照一定的顺序和规则执行,例如使用锁来防止数据竞争。

同步任务的实现需要考虑多个线程之间的协作和同步,以确保数据的正确性和程序的正确执行。

// Index.ets代码
import { taskpool} from '@kit.ArkTS';


// 步骤1: 定义并发函数,实现业务逻辑
@Concurrent
async function taskpoolFunc(num: number): Promise<number> {
  // 根据业务逻辑实现相应的功能
  let tmpNum: number = num + 100;
  return tmpNum;
}

async function mainFunc(): Promise<void> {
  // 步骤2: 创建任务并执行
  let task1: taskpool.Task = new taskpool.Task(taskpoolFunc, 1);
  let res1: number = await taskpool.execute(task1) as number;
  let task2: taskpool.Task = new taskpool.Task(taskpoolFunc, res1);
  let res2: number = await taskpool.execute(task2) as number;
  // 步骤3: 对任务返回的结果进行操作
  console.info("taskpool: task res1 is: " + res1);
  console.info("taskpool: task res2 is: " + res2);
}

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(async () => {
            mainFunc();
          })
      }
      .width('100%')
      .height('100%')
    }
  }
}

在鸿蒙Next中,taskpool任务依赖通过TaskGroup管理,支持addDependency()方法建立任务间依赖关系。Promise回调时序遵循JS标准规范:then()/catch()/finally()按注册顺序执行,但需注意微任务队列特性。任务池中的异步任务完成时会触发Promise回调,但跨线程任务需通过sendData()/postMessage()进行线程间通信。任务依赖的执行顺序优先于Promise回调链。

在HarmonyOS Next的taskpool中,任务依赖确实能保证执行顺序,但需要注意.then回调的执行时机。根据您提供的代码示例:

  1. 任务依赖关系:task1依赖task2,task2依赖task3,taskpool会严格按照task3→task2→task1的顺序执行这些任务。

  2. Promise回调时序:taskpool.execute()返回的Promise回调(.then)是在主线程执行的,而任务本身是在工作线程执行的。因此:

  • 任务本身的执行顺序是保证的(task3先于task2,task2先于task1)
  • 但.then回调的执行时序取决于事件循环,不能保证task1.then一定在task2执行前完成
  1. 如果task2需要task1.then的结果,这种设计是不安全的。应该:
  • 要么将依赖逻辑放在任务函数内部
  • 要么通过Promise链式调用确保顺序
  1. 在您示例中,三个execute()是并行调用的,虽然依赖关系会保证任务执行顺序,但.then回调可能交错执行。

建议重构代码,使用单个execute()调用配合Promise链,或者将依赖逻辑移到任务函数内部,才能确保严格的执行顺序。

回到顶部