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

WPF应用在Windows睡眠/唤醒后窗口无响应问题求助

问题根因

  • 睡眠挂起时未清理已打开的MainWindow实例,系统销毁窗口句柄后,静态变量仍持有无效实例,后续操作该实例会触发UI线程死锁
  • 每次系统唤醒重复调用ConfNotifyIcon(),未清理旧的NotifyIcon实例和绑定的事件委托,重复绑定导致消息队列堵塞
  • 未在应用退出时解绑SystemEvents.PowerModeChanged事件,导致内存泄漏和重复回调
  • 跨线程操作UI的隐式问题:System.Timers.Timer运行在线程池线程,部分场景下调度UI操作会和睡眠唤醒后的消息循环冲突

解决方案

1. 完善挂起时的资源清理逻辑

修改PrepareLock方法,同步清理MainWindow实例:

private void PrepareLock()
{
    notifyIcon?.Dispose();
    cw?.Close();
    // 新增MainWindow清理逻辑
    if (mw != null)
    {
        if (!mw.IsClosed) 
        {
            mw.Close();
        }
        mw = null;
    }
}

2. 避免NotifyIcon事件重复绑定

修改ConfNotifyIcon方法,先清理旧实例再创建新实例:

private void ConfNotifyIcon()
{
    // 先清理旧的NotifyIcon资源和绑定事件
    if (notifyIcon != null)
    {
        notifyIcon.DoubleClick -= OnClick;
        notifyIcon.Dispose();
    }
    notifyIcon = new Forms.NotifyIcon();
    notifyIcon.Icon = new System.Drawing.Icon("Images/Wellformation.ico");
    notifyIcon.DoubleClick += OnClick;
    notifyIcon.ContextMenuStrip = new Forms.ContextMenuStrip();
    notifyIcon.ContextMenuStrip.Items.Add("Open", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnClick);
    notifyIcon.ContextMenuStrip.Items.Add("Close", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnClose);
    notifyIcon.ContextMenuStrip.Items.Add(new Forms.ToolStripSeparator());
    notifyIcon.ContextMenuStrip.Items.Add("Exit", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnExit);
}

3. 优化MainWindow打开逻辑,避免无效实例操作

修改OpenMain方法,每次打开前先清理旧实例:

private void OpenMain()
{
    // 清理旧的MainWindow实例,忽略无效句柄异常
    if (mw != null)
    {
        try
        {
            if (!mw.IsClosed) 
            {
                mw.Close();
            }
        }
        catch 
        { 
            // 捕获系统已销毁窗口句柄导致的异常
        }
        mw = null;
    }
    mw = new MainWindow();
    mw.Show();
    mw.Activate();
}

4. 解绑系统事件避免泄漏

修改OnExit方法,退出前解绑PowerModeChanged事件:

private void OnExit(object sender, EventArgs e)
{
    SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
    PrepareLock();
    Application.Current.Shutdown();
}

5. 可选优化:替换线程池Timer为WPF调度Timer

将ConfigWindow中的System.Timers.Timer替换为DispatcherTimer,完全在UI线程运行,避免跨线程调度冲突:

// 替换原有Timer定义
private System.Windows.Threading.DispatcherTimer at = new System.Windows.Threading.DispatcherTimer();

private void ActionTimer()
{
    at.Interval = TimeSpan.FromMinutes(1);
    at.Tick += ChecktActions;
    at.Start();
}

private void ChecktActions(object sender, EventArgs e)
{
    // 原有逻辑无需修改,当前事件已在UI线程触发
}

内容的提问来源于stack exchange,提问作者Rich G

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 07:15:05