HarmonyOS 鸿蒙Next中一个worker线程创建另一个worker线程后立即退出会导致创建失败

HarmonyOS 鸿蒙Next中一个worker线程创建另一个worker线程后立即退出会导致创建失败 我在主线程中用new worker.ThreadWorker创建一个worker线程A:

1、在这个worker线程A里创建用new worker.ThreadWorker创建一个worker线程B后,立即调用workerPort.close()让worker线程A退出,此时发现worker线程B没有运行,hilog里打印如下日志:

02-24 17:38:08.990 29804-30039 C03f01/NAPI com.examp…monytest E [(:1428)(CreateWorkerEnv)] worker:: host thread is stop

02-24 17:38:08.990 29804-30039 C03f01/NAPI com.examp…monytest E [(:1470)(ExecuteInThread)] worker:: create workerEnv failed

2、在这个worker线程A里创建用new worker.ThreadWorker创建一个worker线程B后,不调用workerPort.close(),此时发现worker线程B正常运行。

问题:我有什么办法能让worker线程A在等待worker线程B正常运行后才退出?


更多关于HarmonyOS 鸿蒙Next中一个worker线程创建另一个worker线程后立即退出会导致创建失败的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

【解决方案】

开发者您好,可以参考多级Worker生命周期管理中的不推荐使用示例第二个示例:

不建议在父Worker发起销毁操作的执行阶段创建子Worker。在创建子Worker线程之前,需确保父Worker线程始终处于存活状态,建议在确定父Worker未发起销毁操作的情况下创建子Worker。

// 父Worker销毁后创建子Worker
workerPort.close();
let childWorker = new worker.ThreadWorker('entry/ets/workers/ChildWorker.ets');

// 子Worker线程未确认创建成功前销毁父Worker
// let childWorker = new worker.ThreadWorker('entry/ets/workers/ChildWorker.ets');
// workerPort.close();

更多关于HarmonyOS 鸿蒙Next中一个worker线程创建另一个worker线程后立即退出会导致创建失败的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


不要让 Worker A 立即退出。通过 Promise、Callback 或者同步原语(如上面提到的 CountDownLatch 逻辑)来阻塞 Worker A 的退出流程,直到确认 Worker B 已经完全初始化并接管了任务。

试试屎山代码呗,不行就sleep嘛。再不行跑个变量,在B去改变变量,当A读到变量变了去关闭A。

你这个办法可行,但是有点麻烦。

在HarmonyOS Next中,主线程或Worker线程创建新Worker线程后立即退出,会导致新Worker线程创建失败。这是因为Worker线程的创建和初始化需要时间,父线程过早退出会中断新Worker的初始化过程,导致资源未正确分配而失败。需确保父线程在新Worker初始化完成前保持活动状态。

在HarmonyOS Next中,Worker线程A创建Worker线程B后立即退出导致B创建失败,是因为Worker线程B的运行依赖于其宿主线程(即线程A)的运行时环境。当线程A过早关闭时,线程B的初始化过程会被中断。

根据你提供的日志 host thread is stopcreate workerEnv failed,可以确认失败原因是宿主线程(线程A)在Worker线程B完成环境初始化和启动之前就退出了。

解决方案:确保线程A在退出前,线程B已成功启动并进入运行状态。

你可以通过线程间通信来实现这一点。核心思路是:让Worker线程B在成功启动后,主动发送一个消息通知Worker线程A,线程A在收到此消息后再安全退出。

代码示例:

  1. 在线程B的脚本文件(例如 workerB.ts)中,在 onReady 生命周期或初始化完成后立即向父线程(线程A)发送一个“已就绪”的消息。

    import worker from '@ohos.worker';
    
    let parentPort = worker.parentPort;
    
    // 当Worker线程B准备就绪时
    parentPort.onReady = function() {
        // 通知父线程(Worker线程A)本线程已启动成功
        parentPort.postMessage({ type: 'WORKER_B_READY' });
    };
    
    // ... 线程B的其他业务逻辑
    
  2. 在线程A的脚本文件(例如 workerA.ts)中,监听来自线程B的消息。收到“就绪”消息后,再关闭自身。

    import worker from '@ohos.worker';
    
    let parentPort = worker.parentPort;
    
    // 创建Worker线程B
    let workerB = new worker.ThreadWorker('entry/ets/workers/workerB.ts');
    
    // 监听来自Worker线程B的消息
    workerB.onmessage = function(message) {
        if (message && message.data && message.data.type === 'WORKER_B_READY') {
            console.log('Worker B is ready. Now Worker A can exit safely.');
            // 确认线程B已就绪后,关闭线程A
            parentPort.close();
        }
    };
    
    // ... 线程A的其他业务逻辑(如果有)
    

关键点:

  • 同步机制:这种方式在父子Worker线程间建立了一个简单的同步点,确保了执行顺序。
  • 生命周期管理:将线程A的退出动作与线程B的启动成功事件绑定,是管理多级Worker线程生命周期的推荐做法。
  • 错误处理:在实际开发中,建议增加超时机制或错误监听,以防线程B启动失败导致线程A一直等待。

通过以上方法,你可以可靠地控制Worker线程A在Worker线程B正常运行后才退出,避免因宿主线程过早退出而导致的创建失败问题。

回到顶部