var flag = threads.atomic(false); 找不到方法atomic

已存档
七月CX · 2 个月前
第 1 条补充
·
2 个月前

// 微信通知监听与模拟操作控制脚本
console.show();
// 隐藏输入框和确定按钮
ui.run(function() {
let mConsoleViewField = runtime.console.getClass().getDeclaredField('mConsoleView');
mConsoleViewField.setAccessible(true);
let refConsoleView = mConsoleViewField.get(runtime.console);
let mConsoleView = refConsoleView.get();
mConsoleView.findViewById(com.stardust.autojs.R.id.input_container).visibility = android.view.View.GONE;
});
// 文档地址 https://docs.hamibot.com/
var flag = threads.atomic(0); // 原子变量,用于线程间通信

// 监听通知的线程
threads.start(function () {
events.observeNotification();
events.on('notification', function(n) {
if (n.getPackageName() === 'com.tencent.mm') {
var text = n.getText();
log(n.getText());
log(n.getPackageName());
log(n.getTitle());
if(n.getPackageName()=="com.tencent.mm"&&n.getText().includes("小程序")){
flag.set(1); // 修改原子变量
}
}
});
});

// 模拟操作的线程
threads.start(function () {
while (true) {
if (flag.get()==1) {
log(2)
// 执行暂停后的操作
click(500, 1000);
flag.set(0); // 重置标志
}

    // 正常模拟操作
    gesture(1000, [100, 100], [500, 500]);
    sleep(1000);
    log(1)
}

}); 这两个线程如何在按下停止按钮后结束线程

回答

Hamibot AI
1
· 2 个月前

根据你的描述,你尝试使用 threads.atomic(false) 来创建一个原子变量,但提示找不到方法。这是因为在 Hamibot 的 threads 模块中,threads.atomic() 仅支持创建整数类型的原子变量(默认值为 0),而不能直接用于布尔值或其它类型。

如果你需要实现布尔类型的线程安全操作,可以考虑使用 ReentrantLock 或者通过封装同步机制来实现。以下是使用 ReentrantLock 实现线程安全的布尔标志示例:

// 文档地址 https://docs.hamibot.com/
var lock = threads.lock();
var flag = false;

// 设置 flag 的线程安全方法
function setFlag(value) {
    lock.lock();
    try {
        flag = value;
    } finally {
        lock.unlock();
    }
}

// 获取 flag 的线程安全方法
function getFlag() {
    lock.lock();
    try {
        return flag;
    } finally {
        lock.unlock();
    }
}

// 子线程修改 flag
threads.start(function () {
    while (true) {
        var current = getFlag();
        log("子线程读取 flag: " + current);
        setFlag(!current);
        sleep(1000);
    }
});

// 主线程同时读取和修改 flag
while (true) {
    var current = getFlag();
    log("主线程读取 flag: " + current);
    setFlag(!current);
    sleep(1000);
}

上面代码展示了如何用 threads.lock() 创建锁对象,并在多线程环境下对布尔变量 flag 进行安全的读写操作。


补充回答 1

要实现在线程运行时按下停止按钮结束线程,你需要:

  1. 创建一个 UI 停止按钮。
  2. 在点击按钮时设置一个标志变量为终止状态。
  3. 修改线程逻辑,在循环中检查该标志以决定是否退出。

以下是修改后的代码示例(文档地址 https://docs.hamibot.com/):

console.show();

// 隐藏输入框和确定按钮
ui.run(function () {
    let mConsoleViewField = runtime.console.getClass().getDeclaredField('mConsoleView');
    mConsoleViewField.setAccessible(true);
    let refConsoleView = mConsoleViewField.get(runtime.console);
    let mConsoleView = refConsoleView.get();
    mConsoleView.findViewById(com.stardust.autojs.R.id.input_container).visibility = android.view.View.GONE;
});

var flag = threads.atomic(0); // 用于线程间通信的原子变量
var running = true; // 控制线程是否继续执行

// 添加一个停止按钮到界面
ui.layout(
    <vertical>
        <button id="stopBtn" text="停止线程"/>
    </vertical>
);

// 点击事件处理
ui.stopBtn.click(function () {
    running = false; // 设置running为false,触发线程退出
    toast("正在停止线程...");
});

// 监听通知的线程
threads.start(function () {
    events.observeNotification();
    events.on('notification', function (n) {
        if (n.getPackageName() === 'com.tencent.mm' && n.getText() && n.getText().includes("小程序")) {
            flag.set(1); // 修改原子变量
        }
    });

    // 循环监听直到running变为false
    while (running) {
        sleep(100); // 轻度休眠避免占用过高资源
    }

    log("通知监听线程已退出");
});

// 模拟操作的线程
threads.start(function () {
    while (running) { // 当running为false时退出循环
        if (flag.get() == 1) {
            log(2);
            click(500, 1000);
            flag.set(0); // 重置标志
        }

        gesture(1000, [100, 100], [500, 500]);
        sleep(1000);
        log(1);
    }

    log("模拟操作线程已退出");
});

实现要点:

  • running 变量:这是一个布尔标志,用来控制线程是否应该继续运行。当点击按钮时将其设为 false
  • 线程内循环检查:每个线程在主循环中都检查 running 的值。一旦发现 running == false,就退出循环,完成清理工作后线程自然结束。
  • 日志输出提示:线程结束时会打印一条信息,帮助确认线程已正确退出。

通过这种方式可以优雅地结束两个线程,同时保持脚本的可控性和可读性。

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