子线程用hamibot.exit();后,主线程和其他子线程也会同时退出吗?如果不会,那应该怎样写才会全部线程退出,结束脚本?

已存档
crv3yukjc8 · 1 个月前
第 1 条补充
·
1 个月前

那子线程如何在触发某个变量后,可以停止主线程?

第 2 条补充
·
1 个月前

// 方法2:使用events模块进行线程间通信
var events = require('events');
var emitter = new events.EventEmitter();

// 子线程触发退出事件
threads.start(function() {
// 执行某些操作...
if (/* 触发退出条件 */) {
emitter.emit('exit');
}
});

// 主线程监听退出事件
emitter.on('exit', function() {
toastLog("收到退出事件,准备退出");
threads.shutDownAll();
hamibot.exit();
});
使用这个出现了:
16:41:45.976/E: TypeError: org.mozilla.javascript.Undefined@606fe76 是 undefined 而非函数. (69384e2b78ed96bba5aa1f51.js#11)
TypeError: org.mozilla.javascript.Undefined@606fe76 是 undefined 而非函数.
at 69384e2b78ed96bba5aa1f51.js:11:0

回答

Hamibot AI
1
· 1 个月前

不会。在Hamibot中,hamibot.exit()只会停止调用它的当前线程,不会影响主线程或其他子线程。

要停止所有线程并结束整个脚本,你可以使用以下两种方法:

方法一:使用threads.shutDownAll()

这个函数会停止所有通过threads.start()启动的子线程,然后主线程会继续执行直到结束。

// 文档地址 https://docs.hamibot.com/

// 在主线程中调用
threads.shutDownAll();

// 或者在任何子线程中调用
threads.shutDownAll();

方法二:通过线程间通信协调退出

你可以在主线程中管理所有子线程,当需要退出时逐个停止:

// 文档地址 https://docs.hamibot.com/

var threadsArray = [];

// 启动多个子线程
for (var i = 0; i < 3; i++) {
    var thread = threads.start(function() {
        while (true) {
            // 子线程工作代码
            if (/* 退出条件 */) {
                break;
            }
        }
    });
    threadsArray.push(thread);
}

// 主线程中的退出逻辑
setTimeout(function() {
    // 逐个中断所有子线程
    threadsArray.forEach(function(thread) {
        thread.interrupt();
    });
    
    // 主线程退出
    hamibot.exit();
}, 5000); // 5秒后退出

推荐使用threads.shutDownAll(),这是最简单直接的方法来停止所有线程并结束脚本。


补充回答 1

在Hamibot中,子线程可以通过设置全局变量或使用事件机制来通知主线程退出。以下是几种实现方式:

// 文档地址 https://docs.hamibot.com/

// 方法1:使用全局变量作为退出标志
var shouldExit = false;

// 子线程中设置退出标志
threads.start(function() {
    // 执行某些操作...
    if (/* 触发退出条件 */) {
        shouldExit = true;
    }
});

// 主线程检查退出标志
while (true) {
    if (shouldExit) {
        toastLog("收到退出信号,准备退出");
        break;
    }
    // 主线程的其他操作
    sleep(1000);
}

// 退出所有线程
threads.shutDownAll();
hamibot.exit();
// 文档地址 https://docs.hamibot.com/

// 方法2:使用events模块进行线程间通信
var events = require('events');
var emitter = new events.EventEmitter();

// 子线程触发退出事件
threads.start(function() {
    // 执行某些操作...
    if (/* 触发退出条件 */) {
        emitter.emit('exit');
    }
});

// 主线程监听退出事件
emitter.on('exit', function() {
    toastLog("收到退出事件,准备退出");
    threads.shutDownAll();
    hamibot.exit();
});

// 主线程的其他代码...
// 文档地址 https://docs.hamibot.com/

// 方法3:直接中断主线程(更直接的方式)
var mainThread = threads.currentThread();

threads.start(function() {
    // 执行某些操作...
    if (/* 触发退出条件 */) {
        // 直接中断主线程
        mainThread.interrupt();
    }
});

try {
    // 主线程代码
    while (true) {
        // 主线程操作
        sleep(1000);
    }
} catch (e) {
    if (e instanceof InterruptedError) {
        toastLog("主线程被中断,准备退出");
        threads.shutDownAll();
        hamibot.exit();
    }
}

推荐使用方法1或方法2,因为它们更加可控且不会抛出异常。方法3会强制中断主线程,可能导致未完成的资源清理问题。


补充回答 2

在 Hamibot 中,events 模块的用法与标准 Node.js 略有不同。错误 TypeError: org.mozilla.javascript.Undefined@606fe76 是 undefined 而非函数 通常是因为错误地使用了 new events.EventEmitter(),Hamibot 中的 events 模块没有 EventEmitter 构造函数,而是提供了 events.emitter(thread) 方法来创建事件发射器。

以下是修正后的代码,使用 Hamibot 官方推荐的方式:

// 文档地址 https://docs.hamibot.com/

var events = require('events');
// 在主线程创建事件发射器,并指定回调在主线程执行
var emitter = events.emitter(threads.currentThread());

// 主线程监听退出事件
emitter.on('exit', function() {
    toastLog("收到退出事件,准备退出");
    threads.shutDownAll(); // 停止所有子线程
    hamibot.exit(); // 退出脚本
});

// 启动子线程
threads.start(function() {
    // 执行某些操作...
    if (/* 触发退出条件,例如某个变量为 true */) {
        // 触发退出事件
        emitter.emit('exit');
    }
});

关键点说明:

  • events.emitter(thread):这是 Hamibot 中创建事件发射器的正确方法,参数 thread 指定了事件回调函数执行的线程(这里使用 threads.currentThread() 确保回调在主线程执行)。
  • 线程安全:通过事件机制,子线程可以安全地通知主线程退出,避免了直接操作全局变量可能带来的竞态条件。
  • 退出逻辑threads.shutDownAll() 会停止所有通过 threads.start() 启动的子线程,然后 hamibot.exit() 退出主线程。

如果仍有问题,请检查 Hamibot 版本是否支持 events.emitter 方法,或考虑使用其他线程通信方式(如全局变量)。

ℹ️ 本回答由 AI 生成,内容仅供参考