Threading - 线程和定时器
EasyBot 提供了完整的定时器功能和线程同步机制,支持延时执行、间隔执行以及多线程环境下的互斥锁操作。
threading 命名空间
threading 命名空间包含定时器和互斥锁相关的函数。
setTimeout()
创建一个定时器,在指定的延迟后执行回调函数。
语法: threading.setTimeout(callback: () => void, delay: number): number
参数:
callback- 要执行的回调函数delay- 延迟时间(毫秒)
返回值: 定时器ID
示例:
const timerId = threading.setTimeout(() => {
logger.info("3秒后执行");
}, 3000);
setInterval()
创建一个间隔定时器,每隔指定的时间执行回调函数。
语法: threading.setInterval(callback: () => void, interval: number): number
参数:
callback- 要执行的回调函数interval- 间隔时间(毫秒)
返回值: 定时器ID
示例:
const intervalId = threading.setInterval(() => {
logger.info("每5秒执行一次");
}, 5000);
clearTimeout()
清除定时器。
语法: threading.clearTimeout(timerId: number): boolean
参数:
timerId- 定时器ID
返回值: 是否成功清除
示例:
const timerId = threading.setTimeout(() => {
logger.info("这不会执行");
}, 1000);
const success = threading.clearTimeout(timerId);
logger.info(`清除成功: ${success}`);
clearInterval()
清除间隔定时器。
语法: threading.clearInterval(timerId: number): boolean
参数:
timerId- 定时器ID
返回值: 是否成功清除
示例:
const intervalId = threading.setInterval(() => {
logger.info("定期执行");
}, 1000);
// 10秒后停止
threading.setTimeout(() => {
const success = threading.clearInterval(intervalId);
logger.info(`停止间隔定时器: ${success}`);
}, 10000);
createMutex()
创建一个互斥锁 (Mutex),用于在多线程环境中同步访问共享资源。
语法 1: threading.createMutex(name: string): Mutex
语法 2: threading.createMutex(initiallyOwned: boolean, name: string): Mutex
参数:
initiallyOwned- (可选) 是否初始为已占用状态,默认为falsename- 互斥锁名称,用于标识系统范围内的互斥锁
返回值: Mutex 对象
示例:
const mutex = threading.createMutex("my-global-lock");
Mutex 接口
Mutex 对象提供了线程同步的原语。
WaitOne()
阻塞当前线程,直到收到信号或超时。
语法 1: WaitOne(): boolean (无限期等待)
语法 2: WaitOne(millisecondsTimeout: number): boolean
语法 3: WaitOne(millisecondsTimeout: number, exitContext: boolean): boolean
参数:
millisecondsTimeout: 等待的毫秒数,-1表示无限等待。exitContext: 是否在等待前退出同步上下文(通常用不到,默认为 false)。
返回值:
true: 成功获取到锁。false: 超时未获取到锁。
ReleaseMutex()
释放当前线程对互斥体的占用。
语法: ReleaseMutex(): void
注意: 只有拥有锁的线程才能释放锁,否则会抛出异常。
使用示例
const mutex = threading.createMutex("resource-lock");
function safeOperation() {
logger.info("尝试获取锁...");
// 尝试获取锁,最多等待 5 秒
if (mutex.WaitOne(5000)) {
try {
logger.info("成功获取锁,开始执行操作");
// 模拟耗时操作
// ...
} finally {
logger.info("释放锁");
mutex.ReleaseMutex();
}
} else {
logger.warning("获取锁超时");
}
}
全局定时器函数
EasyBot 还提供了兼容标准 JavaScript 的全局定时器函数。
setTimeout()
全局版本的 setTimeout 函数,支持额外参数传递。
语法: setTimeout(callback: Function, delay?: number, ...args: any[]): number
参数:
callback- 要执行的回调函数delay- 延迟时间(毫秒),默认为0args- 传递给回调函数的参数
返回值: 定时器ID
示例:
// 基础用法
const timerId = setTimeout(() => {
logger.info("延时执行");
}, 2000);
// 传递参数
setTimeout((name, age) => {
logger.info(`Hello ${name}, you are ${age} years old`);
}, 1000, "张三", 25);
setInterval()
全局版本的 setInterval 函数,支持额外参数传递。
语法: setInterval(callback: Function, interval?: number, ...args: any[]): number
参数:
callback- 要执行的回调函数interval- 间隔时间(毫秒),默认为0args- 传递给回调函数的参数
返回值: 定时器ID
示例:
// 基础用法
const intervalId = setInterval(() => {
logger.info("定期执行");
}, 3000);
// 传递参数
setInterval((message) => {
logger.info(message);
}, 2000, "定时消息");
clearTimeout()
全局版本的 clearTimeout 函数。
语法: clearTimeout(timerId: number): void
参数:
timerId- 定时器ID
示例:
const timerId = setTimeout(() => {
logger.info("这不会执行");
}, 5000);
clearTimeout(timerId);
clearInterval()
全局版本的 clearInterval 函数。
语法: clearInterval(timerId: number): void
参数:
timerId- 定时器ID
示例:
const intervalId = setInterval(() => {
logger.info("定期执行");
}, 1000);
// 5秒后停止
setTimeout(() => {
clearInterval(intervalId);
}, 5000);
实用示例
延时发送消息
bus.on("group_message_event", (event) => {
if (event.RawMessage === "/remind") {
event.Context.Reply(new MessageChain().Text("我会在30秒后提醒你"));
setTimeout(() => {
event.Context.Reply(new MessageChain().Text("⏰ 时间到了!"));
}, 30000);
}
});
定期任务
// 每小时发送一次群公告
const hourlyAnnouncement = setInterval(() => {
const message = new MessageChain()
.Text("📢 每小时公告:请遵守群规,文明聊天!");
// 向所有群发送消息(需要根据实际情况获取群列表)
// context.SendGroupMessageAsync(selfId, groupId, message);
}, 3600000); // 1小时 = 3600000毫秒
倒计时功能
function startCountdown(context, selfId, peerId, seconds) {
let remaining = seconds;
const countdownInterval = setInterval(() => {
if (remaining <= 0) {
clearInterval(countdownInterval);
context.SendGroupMessageAsync(
selfId,
peerId,
new MessageChain().Text("⏰ 倒计时结束!")
);
return;
}
if (remaining <= 10 || remaining % 10 === 0) {
context.SendGroupMessageAsync(
selfId,
peerId,
new MessageChain().Text(`倒计时: ${remaining} 秒`)
);
}
remaining--;
}, 1000);
return countdownInterval;
}
// 使用示例
bus.on("group_message_event", (event) => {
if (event.RawMessage.startsWith("/countdown ")) {
const seconds = parseInt(event.RawMessage.split(" ")[1]);
if (seconds > 0 && seconds <= 300) { // 最多5分钟
startCountdown(event.AdapterContext, event.SelfId, event.PeerId, seconds);
}
}
});
定时清理任务
const activeUsers = new Map();
// 记录用户活动
bus.on("group_message_event", (event) => {
activeUsers.set(event.SenderId, Date.now());
});
// 每10分钟清理不活跃用户记录
setInterval(() => {
const now = Date.now();
const tenMinutes = 10 * 60 * 1000;
for (const [userId, lastActive] of activeUsers.entries()) {
if (now - lastActive > tenMinutes) {
activeUsers.delete(userId);
}
}
logger.info(`活跃用户数量: ${activeUsers.size}`);
}, 600000); // 10分钟