【问题标题】:What happens to a SynchronizationContext when the main window closes?当主窗口关闭时 SynchronizationContext 会发生什么?
【发布时间】:2011-12-18 23:16:12
【问题描述】:

我正在编写一个游戏,它的界面使用 WPF,并使用 Direct3D11 渲染世界。渲染发生在它自己的线程上,但它需要在窗口中使用 D3DImage,所以我需要在渲染时使用 SynchronizationContext 切换到 UI 线程。当游戏第一次启动时,我从 Application.Current.Dispatcher 创建了一个 DispatcherSynchronizationContext。发生这种情况一段时间后,会创建一个窗口,然后将其存储在 Application.Current.MainWindow 中。当需要渲染时,我必须像这样切换到上下文:

async {
    ...
    do! Async.SwitchToContext state.Context
    //render stuff

}

在主窗口关闭之前一切都很好。一旦发生这种情况,我的 Application.Exit 处理程序就会运行,它会告诉所有子系统关闭,然后等待它们的响应。问题是渲染线程在下一个 Async.SwitchToContext 上挂起,或者如果切换已经在窗口关闭之前发生,那么它会在实际渲染期间的某个时间挂起,因此它永远无法响应关闭请求。

DispatcherSynchronizationContext 不会变为 null,并且 DSC 的 HasShutdownStarted 和 HasShutdownFinished 的值都是 false。我也没有任何例外。应用程序仍在运行,它不会退出,直到它得到所有子系统的响应。

程序中此时发生了什么?应用程序仍在运行,所以它的调度程序应该仍然存在,所以我应该仍然能够切换到它的上下文。在窗口关闭之前和之后 SynchronizationContext 没有任何变化,这会让我相信它不再有效,所以我不知道如何检查它是否可以安全切换。

【问题讨论】:

  • Application.Current.ShutdownMode 的值是多少?如果是 ShutdownMode.OnMainWindowClose,那么您看到的行为是预期的。
  • 是否打开了另一个窗口?你有没有试过把它改成ShutdownMode.OnExplicitShutdown
  • 没有其他窗口。我刚刚尝试了 OnExplicitShutdown,它解决了这个问题。你能帮我理解其中的区别吗?在这两种情况下,调度程序在我尝试使用它时都没有关闭。

标签: wpf f#


【解决方案1】:

(转自cmets)

对于您的 Application.Current.ShutdownMode 值,您看到的行为是预期的 - 因为当您的主窗口关闭时,除了您的主窗口之外,您没有打开其他窗口(引用文档)

当应用程序中的最后一个窗口关闭时,Windows Presentation Foundation (WPF) 会隐式调用 Shutdown

当然,调用Shutdown(直接或间接)显式终止进程。

如果您希望您的进程在所有窗口都关闭后仍保持活动状态,则必须将值 ShutdownMode.OnExplicitShutdown 分配给 Application.Current.ShutdownMode

某些应用程序的生命周期可能不依赖于主窗口或最后一个窗口何时关闭,或者可能根本不依赖于窗口。对于这些场景,您需要将ShutdownMode 属性设置为OnExplicitShutdown,这需要显式调用Shutdown 方法来停止应用程序。否则,应用程序将继续在后台运行。

对我来说,这听起来就像你的确切场景。 ;-]

【讨论】:

  • 正确,但是“您可以处理 Exit 事件以检测应用程序何时将停止运行,以执行任何适当的处理。”我已经向 Exit 添加了一个处理程序,并且我试图告诉我的渲染器在该处理程序内关闭。因为它说“即将停止运行”,所以我认为它会没事的。感谢您纠正我。
  • 实际上,SessionEnding 似乎仅在用户注销/关闭时才有效。应用程序刚刚关闭时对我没有影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
  • 2015-03-25
  • 1970-01-01
  • 1970-01-01
  • 2015-11-17
  • 1970-01-01
  • 2020-05-05
相关资源
最近更新 更多