Linux系统下Electron应用锁屏时SetTimeout失效的解决方案咨询
解决Electron在Linux锁屏时SetTimeout失效及捕获锁屏状态问题
一、捕获Linux锁屏/解锁事件
Electron官方未提供Linux下的锁屏事件API,可通过DBus监听桌面环境的屏幕保护信号实现,主流桌面环境(GNOME、KDE、Xfce等)均基于DBus通信。
实现步骤
- 安装DBus Node.js模块(推荐
dbus-next):
npm install dbus-next
- 在Electron主进程中编写监听逻辑,兼容不同桌面环境:
const { app } = require('electron'); const { sessionBus } = require('dbus-next'); async function setupScreenLockMonitor() { // 尝试监听GNOME桌面锁屏信号 try { const bus = sessionBus(); const screensaverProxy = await bus.getProxyObject('org.gnome.ScreenSaver', '/org/gnome/ScreenSaver'); const screensaverIface = screensaverProxy.getInterface('org.gnome.ScreenSaver'); screensaverIface.on('ActiveChanged', (isLocked) => { if (isLocked) { // 处理锁屏逻辑 console.log('系统已锁屏'); } else { // 处理解锁逻辑 console.log('系统已解锁'); } }); return; } catch (e) {} // 尝试监听KDE/Freedesktop标准锁屏信号 try { const bus = sessionBus(); const screensaverProxy = await bus.getProxyObject('org.freedesktop.ScreenSaver', '/org/freedesktop/ScreenSaver'); const screensaverIface = screensaverProxy.getInterface('org.freedesktop.ScreenSaver'); screensaverIface.on('ActiveChanged', (isLocked) => { isLocked ? console.log('系统已锁屏') : console.log('系统已解锁'); }); return; } catch (e) {} // 尝试监听Xfce桌面锁屏信号 try { const bus = sessionBus(); const screensaverProxy = await bus.getProxyObject('org.xfce.ScreenSaver', '/org/xfce/ScreenSaver'); const screensaverIface = screensaverProxy.getInterface('org.xfce.ScreenSaver'); screensaverIface.on('ActiveChanged', (isLocked) => { isLocked ? console.log('系统已锁屏') : console.log('系统已解锁'); }); return; } catch (e) { console.warn('当前桌面环境暂不支持监听锁屏事件'); } } // 在应用就绪后启动监听 app.whenReady().then(setupScreenLockMonitor);
二、让SetTimeout在锁屏时持续运行
Linux锁屏时系统可能会将应用进程挂起以节省功耗,导致定时器暂停,可通过以下两种方式解决:
方法1:使用Electron powerSaveBlocker阻止进程挂起
Electron内置的powerSaveBlocker模块可阻止系统进入低功耗模式,保证进程持续运行:
const { powerSaveBlocker } = require('electron'); // 启动阻止显示器休眠的锁(不会完全禁用节电,仅保证进程运行) const blockerId = powerSaveBlocker.start('prevent-display-sleep'); // 验证锁是否启动成功 console.log('电源锁状态:', powerSaveBlocker.isStarted(blockerId)); // 当不需要时关闭锁(比如应用退出或进入后台) // powerSaveBlocker.stop(blockerId);
方法2:使用Worker Threads独立运行定时器
将定时器逻辑放在Node.js工作线程中,避免主线程被系统挂起影响定时器:
// main.js 主进程 const { Worker } = require('worker_threads'); const path = require('path'); // 创建工作线程 const timerWorker = new Worker(path.join(__dirname, 'timer-worker.js')); // 监听工作线程消息 timerWorker.on('message', (msg) => { console.log('定时器触发:', msg); }); // timer-worker.js 工作线程 const { parentPort } = require('worker_threads'); function runTimer() { setTimeout(() => { parentPort.postMessage('定时任务执行'); runTimer(); // 循环触发 }, 1000); } runTimer();
内容的提问来源于stack exchange,提问作者Henil Mehta
相关产品推荐
相关产品推荐

