You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 15:04:51