Eclipse RCP应用弹窗打开时登录会话超时功能失效求助
解决方案:Eclipse RCP弹窗时会话超时失效问题
问题根源在于SWT模态对话框(如MessageDialog)会启动独立的嵌套事件循环,此时WorkbenchAdvisor.eventLoopIdle()仅在工作台主事件循环空闲时触发,嵌套循环运行期间主循环的空闲事件会被暂停,导致超时检测失效。
改用Display.timerExec()实现定时检测是更可靠的方案,它会在所有事件循环(包括嵌套循环)的空闲阶段执行检测逻辑,确保弹窗状态下超时功能正常。
1. 修改SessionManager类,添加定时器管理逻辑
public class SessionManager { private long timeStampLastMs; private long timeOutTimeMs = 20000L; private static SessionManager sessionManager = null; private Display display; private int timerId = -1; // 保存定时器ID用于取消 private SessionManager() { resetActivityTimeOut(); // 初始化活动时间戳 } public static SessionManager getSessionManager() { if (sessionManager == null) { sessionManager = new SessionManager(); } return sessionManager; } public synchronized boolean isActivityTimeOut() { long now = System.currentTimeMillis(); return timeOutTimeMs < (now - timeStampLastMs); } public synchronized void resetActivityTimeOut() { timeStampLastMs = System.currentTimeMillis(); } // 启动超时检测定时器,每隔1秒检查一次(可按需调整间隔) public void startTimeoutCheck(Display targetDisplay) { this.display = targetDisplay; // 避免重复启动,先取消已有定时器 if (timerId != -1) { display.timerExec(timerId, null); } timerId = display.timerExec(1000, new Runnable() { @Override public void run() { if (isActivityTimeOut()) { timeoutScreen(); display.dispose(); System.exit(0); } else { // 循环触发检测任务 timerId = display.timerExec(1000, this); } } }); } // 关闭工作台时取消定时器,避免资源泄漏 public void stopTimeoutCheck() { if (display != null && timerId != -1) { display.timerExec(timerId, null); timerId = -1; } } public void timeoutScreen() { int defaultIndex = 0; MessageDialog dialog = new MessageDialog(null, "Information", null, "Login session expired. Please close this window and restart application", MessageDialog.INFORMATION, new String[]{IDialogConstants.OK_LABEL}, defaultIndex); dialog.open(); } }
2. 调整ApplicationWorkbenchAdvisor,移除eventLoopIdle逻辑,改用定时器启停
public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { @Override public void postStartup() { super.postStartup(); // 工作台启动完成后启动超时检测 SessionManager.getSessionManager().startTimeoutCheck(Display.getCurrent()); } @Override public boolean preShutdown() { // 工作台关闭前取消定时器 SessionManager.getSessionManager().stopTimeoutCheck(); return super.preShutdown(); } // 保留原有的其他工作台配置方法... }
3. 保留原有UI活动监听逻辑
Application类中监听KeyUp、MouseUp、Activate事件重置时间戳的代码无需修改,确保用户操作能正确刷新超时计时。
关键说明
Display.timerExec()会将检测任务加入事件队列,所有事件循环(主窗口、弹窗嵌套循环)空闲时都会执行,解决了弹窗状态下检测中断的问题。- 定时器间隔设为1秒是平衡检测及时性和性能的选择,可根据实际需求调整(如5秒)。
- 新增
stopTimeoutCheck()方法,在工作台关闭时清理定时器,避免内存泄漏。
内容的提问来源于stack exchange,提问作者user2125853
相关产品推荐
相关产品推荐

