线程管理 API
Bilup 提供了广泛的线程管理功能,用于高级脚本控制和执行。此 API 允许你在运行时监控、控制和操作脚本的执行。
概述
Bilup 中的线程代表正在执行的脚本。每个运行的脚本(从绿旗、积木点击、广播等)都会创建一个线程,管理其执行状态、栈帧和局部变量。
线程基础
什么是线程?
线程是脚本的执行上下文。它包含:
- 脚本的执行栈
- 当前正在执行的积木
- 局部变量和存储
- 执行状态(运行中、暂停、完成)
- Warp 模式状态
访问线程
// 获取所有活动线程
const allThreads = vm.runtime.threads;
// 获取特定目标的线程
const targetThreads = vm.runtime.threads.filter(thread =>
thread.target === specificTarget
);
// 检查线程是否活动
const isRunning = vm.runtime.isActiveThread(someThread);
线程监控
基本线程信息
// 线程属性
const thread = vm.runtime.threads[0];
console.log(thread.topBlock); // 顶层积木的 ID
console.log(thread.target); // 运行线程的目标(角色/舞台)
console.log(thread.isKilled); // 线程是否已停止
console.log(thread.stack); // 当前执行栈
console.log(thread.stackClick); // 是否通过点击积木启动
console.log(thread.updateMonitor); // 是否应更新变量监视器
线程状态
// 线程状态常量
const ThreadStatus = {
RUNNING: 0,
PROMISE_WAIT: 1,
YIELD: 2,
YIELD_TICK: 3,
DONE: 4
};
// 检查线程状态
if (thread.status === ThreadStatus.RUNNING) {
console.log('线程正在运行');
} else if (thread.status === ThreadStatus.DONE) {
console.log('线程已完成执行');
}
线程控制
启动线程
// 从积木启动新线程
const newThread = vm.runtime._pushThread(
blockId, // 要从其开始的积木 ID
target, // 要在其上运行的目标
{
stackClick: true, // 标记为点击启动
updateMonitor: false // 不更新监视器
}
);
// 如果可用,启用编译
if (vm.runtime.compilerOptions.enabled) {
newThread.tryCompile();
}
停止线程
// 停止特定线程
thread.stopThisScript();
// 强制终止线程
vm.runtime._stopThread(thread);
// 停止所有线程
vm.runtime.stopAll();
// 停止目标的所有线程
vm.runtime.stopForTarget(target);
重新启动线程
// 重新启动线程(如果可能)
vm.runtime._restartThread(thread);
// 通过创建新线程强制重新启动
const restartedThread = vm.runtime._pushThread(
thread.topBlock,
thread.target,
{ stackClick: true }
);
高级线程管理
线程监控系统
创建监控系统以跟踪特定线程:
// 线程监控存储
const monitoredThreads = {};
// 用自定义 ID 监控线程
function monitorThread(threadId, thread) {
monitoredThreads[threadId] = thread;
// 添加自定义属性
thread.customStorage = {};
thread.monitorId = threadId;
}
// 检查监控线程是否正在运行
function isMonitoredThreadRunning(threadId) {
const thread = monitoredThreads[threadId];
return thread && vm.runtime.isActiveThread(thread);
}
// 停止监控线程
function stopMonitoredThread(threadId) {
const thread = monitoredThreads[threadId];
if (thread) {
thread.stopThisScript();
}
}
自定义线程存储
在线程中存储数据以在积木间持久化:
// 在线程中存储数据
function storeInThread(thread, key, value) {
if (!thread.customStorage) {
thread.customStorage = {};
}
thread.customStorage[key] = value;
}
// 从线程检索数据
function getFromThread(thread, key) {
if (!thread.customStorage) {
thread.customStorage = {};
}
return thread.customStorage[key];
}
// 在自定义积木中的示例用法
function myCustomBlock(args, util) {
const thread = util.thread;
// 存储一些状态
storeInThread(thread, 'counter',
(getFromThread(thread, 'counter') || 0) + 1
);
return getFromThread(thread, 'counter');
}
栈帧管理
理解栈帧
栈帧表示脚本嵌套每个级别的执行上下文:
// 访问当前栈帧
const currentFrame = thread.peekStackFrame();
console.log(currentFrame.isLoop); // 是否在循环积木中
console.log(currentFrame.warpMode); // 是否在 warp 模式
console.log(currentFrame.params); // 积木参数
console.log(currentFrame.executionContext); // 执行上下文
栈帧创建
// 创建新栈帧(高级用法)
const StackFrame = vm.runtime.sequencer.constructor.StackFrame;
const newFrame = new StackFrame(warpMode);
newFrame.op = blockInfo;
newFrame.params = blockParams;
// 推送到线程栈
thread.pushStackFrame(newFrame);
积木执行控制
控制积木执行
// 跳转到下一个积木
thread.goToNextBlock();
// 获取当前正在执行的积木
const currentBlock = thread.peekStack();
// 推送新积木执行
thread.pushStack(blockId);
// 从栈弹出当前积木
const poppedBlock = thread.popStack();
分支执行
// 执行特定分支(子栈)
const branchBlockId = target.blocks.getBranch(parentBlockId);
if (branchBlockId) {
thread.pushStack(branchBlockId);
}
// 使用自定义目标执行分支
function executeBranchInTarget(branchId, newTarget) {
const newThread = vm.runtime._pushThread(
branchId,
newTarget,
{ stackClick: true }
);
return newThread;
}
内联执行
内联运行代码
创建立即执行并返回值的线程:
function executeInline(blockId, target, parentThread) {
// 创建用于内联执行的模拟线程
const inlineThread = new parentThread.constructor(
parentThread.topBlock,
target,
{ stackClick: false, updateMonitor: false }
);
// 设置线程属性
inlineThread.topBlock = blockId;
inlineThread.stack = [blockId];
inlineThread.target = target;
inlineThread.blockContainer = target.blocks;
// 立即执行
const sequencer = vm.runtime.sequencer;
sequencer.stepThread(inlineThread);
// 如果完成则返回结果
if (inlineThread.status === 4) { // 完成
return inlineThread.inlineReturn || '';
}
// 处理异步执行
return new Promise((resolve) => {
vm.runtime.on('AFTER_EXECUTE', function checkComplete() {
if (inlineThread.status === 4 || inlineThread.inlineReturn !== undefined) {
vm.runtime.off('AFTER_EXECUTE', checkComplete);
resolve(inlineThread.inlineReturn || '');
}
});
});
}