You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WPF:所有者窗口被程序关闭后ShowDialog()不返回致应用挂起

WPF应用挂起原因分析

先把你的代码贴出来方便梳理:

private void MainWindow_Loaded(object sender, RoutedEventArgs e) { 
    var window1 = new TestWindow(); 
    window1.Show(); 
    var timer = new Timer(); 
    timer.Interval = TimeSpan.FromSeconds(3).TotalMilliseconds; 
    timer.Elapsed += (s, e1) => Application.Current.Dispatcher.BeginInvoke((Action) (() => window1.Close())); 
    timer.Start(); 
    var window2 = new TestWindow(); 
    window2.Owner = window1; 
    window2.ShowDialog(); 
}

咱们一步步拆解导致应用挂起的核心问题:

  • 执行流程的冲突点
    你启动window1(非模态窗口)后,又创建了window2并把window1设为它的Owner,随后调用window2.ShowDialog()——这个方法会阻塞当前的UI线程,直到window2被关闭。同时你设置了3秒后关闭window1的定时器。

  • Owner窗口关闭的连锁反应
    3秒后定时器触发,通过Dispatcher异步调用关闭window1。在WPF中,当一个窗口的Owner被关闭时,系统会自动关闭所有以它为Owner的子窗口,也就是window2会被自动关闭。

  • 挂起的根源
    window2.ShowDialog()在MainWindow的UI线程上处于阻塞等待状态,但window2的关闭操作是通过异步的Dispatcher调用触发的。当window2被强制关闭时,它需要完成ShowDialog()的收尾逻辑(比如返回DialogResult、释放相关资源),但此时UI线程的消息循环因为“阻塞等待”和“异步关闭”的冲突,陷入了无法正常推进的状态,最终导致整个应用挂起。

如果要验证这个结论,你可以做两个小测试:

  • window2.ShowDialog()改成window2.Show()(非模态),挂起现象会消失
  • 调整定时器逻辑,先关闭window2再关闭window1,也能避免挂起

内容的提问来源于stack exchange,提问作者adrian h.

火山引擎 最新活动