通用 Windows 平台 (UWP) 应用生命周期
本主题介绍从启动到关闭时通用 Windows 平台(UWP)应用的生命周期。
一点历史
在 Windows 8 之前,应用具有简单的生命周期。 Win32 和 .NET 应用正在运行或未运行。 当用户将他们最小化或离开它们时,他们将继续运行。 这很好,直到便携式设备和电源管理变得越来越重要。
Windows 8 引入了具有 UWP 应用的新应用程序模型。 在较高级别上,添加了新的挂起状态。 用户最小化 UWP 应用或切换到另一个应用后不久将暂停。 这意味着应用的线程已停止,并且应用保留在内存中,除非操作系统需要回收资源。 当用户切换回应用时,可以快速还原到正在运行的状态。
应用在后台(例如后台任务、扩展执行和活动赞助的执行)时需要继续运行(例如,允许应用继续在后台播放媒体的 BackgroundMediaEnabled 功能)。 此外,即使应用已暂停甚至终止,后台传输操作也可以继续。 有关详细信息,请参阅 如何下载文件。
默认情况下,不在前台的应用将暂停。 这会导致为当前在前台的应用节省电源和更多资源。
暂停状态会为你添加开发人员的新要求,因为操作系统可以选择终止暂停的应用以释放资源。 终止的应用仍将显示在任务栏中。 当用户单击它时,应用必须还原它在终止之前的状态,因为用户不会知道系统关闭了应用。 他们会认为,它一直在后台等待,而他们正在做其他事情,并期望它处于相同的状态,当他们离开它。 在本主题中,我们将了解如何实现此目的。
Windows 10 版本 1607 引入了另外两个应用模型状态: 在前台 运行,并在 后台运行。 我们将在后续部分中查看这些其他状态。
应用执行状态
此图表示从 Windows 10 版本 1607 开始的可能应用模型状态。 让我们演练 UWP 应用的典型生命周期。
应用在启动或激活应用时进入后台状态运行。 如果应用需要由于前台应用启动而进入前台,则应用将获取 LeavingBackground 事件。
尽管“已启动”和“已激活”可能类似于类似术语,但它们引用了操作系统启动应用的不同方式。 让我们先看看启动应用。
应用启动
启动应用时调用 OnLaunched 方法。 它传递了 LaunchActivatedEventArgs 参数,该参数提供传递给应用的参数、启动应用的磁贴的标识符以及应用所在的以前状态。
从 LaunchActivatedEventArgs.PreviousExecutionState 获取应用的上一 状态,该状态返回 ApplicationExecutionState。 其值和由于该状态而采取的相应操作如下所示:
ApplicationExecutionState | 说明 | 采取的操作 |
---|---|---|
NotRunning | 应用可能处于此状态,因为它自用户上次重新启动或登录以来尚未启动。 如果它正在运行,但随后崩溃,或者用户之前关闭了它,则它也可能处于此状态。 | 初始化应用,就像它首次在当前用户会话中运行一样。 |
已挂起 | 用户要么最小化,要么从你的应用切换,并在几秒钟内没有返回到它。 | 当应用暂停时,其状态将保留在内存中。 只需重新获取应用暂停时释放的任何文件句柄或其他资源。 |
终止 | 应用以前已暂停,但随后在某个时候关闭,因为系统需要回收内存。 | 还原用户在离开应用时处于的状态。 |
ClosedByUser | 用户使用系统关闭按钮或 Alt+F4 关闭了应用。 当用户关闭应用时,它将先挂起,然后终止。 | 由于应用实质上已完成导致终止状态的相同步骤,因此以与终止状态相同的方式处理。 |
正在运行 | 当用户尝试再次启动应用时,该应用已打开。 | 无变化。 请注意,不会启动应用的另一个实例。 仅激活已运行的实例。 |
注意
当前用户会话 基于 Windows 登录。 只要当前用户尚未注销、关闭或重启 Windows,当前用户会话将持续存在锁屏身份验证、切换用户等事件。
需要注意的一个重要情况是,如果设备有足够的资源,操作系统将预启动已选择加入该行为的常用应用,以优化响应能力。 预启动的应用在后台启动,然后快速暂停,以便在用户切换到它们时恢复,这比启动应用更快。
由于预启动,可能会由系统(而不是用户)启动应用的 OnLaunched() 方法。 由于应用在后台预启动,因此可能需要在 OnLaunched()中采取不同的操作。 例如,如果你的应用在启动时开始播放音乐,则它们将不知道它来自何处,因为应用在后台预启动。 应用在后台预启动后,随后会调用 Application.Suspending。 然后,当用户启动应用时,将调用恢复事件以及 OnLaunched() 方法。 有关如何处理预启动方案的其他信息,请参阅 “处理应用预启动 ”。 仅预启动选择加入的应用。
当应用启动时,Windows 会显示应用的初始屏幕。 若要配置初始屏幕,请参阅 “添加初始屏幕”。
显示初始屏幕时,应用应注册事件处理程序并设置初始页面所需的任何自定义 UI。 务必使在应用程序的构造函数和 OnLaunched() 中运行的这些任务在数秒内完成,否则系统可能会认为应用未响应并终止它。 如果应用需要从网络请求数据,或者需要从磁盘检索大量数据,则应在启动外部完成这些活动。 应用可以使用自己的自定义加载 UI 或延长的初始屏幕,同时等待长时间运行的操作完成。 有关详细信息,请参阅“显示初始屏幕”以获取更多时间和初始屏幕示例。
应用完成启动后,它将进入“正在运行”状态,初始屏幕消失,并清除所有初始屏幕资源和对象。
应用激活
与用户启动相比,应用可由系统激活。 应用可能由合约(如共享协定)激活。 或者,可以激活它以处理自定义 URI 协议或具有应用注册以处理的扩展名的文件。 有关应用可激活方式的列表,请参阅 ActivationKind。
Windows.UI.Xaml.Application 类定义可以重写的方法,以处理应用可能激活的各种方式。 OnActivated 可以处理所有可能的激活类型。 但是,使用特定方法来处理最常见的激活类型更为常见,并使用 OnActivated 作为不太常见的激活类型的回退方法。 以下是特定激活的其他方法:
OnCachedFileUpdaterActivated
OnFileActivated
OnFileOpenPickerActivated OnFileSavePickerActivated
OnSearchActivated
OnShareTargetActivated
这些方法的事件数据包括上面看到的相同 PreviousExecutionState 属性,该属性指示应用在激活之前处于哪个状态。 按照上述 应用启动 部分中所述的方式解释状态和应执行的操作。
请注意 ,如果使用计算机的管理员帐户登录,则无法激活 UWP 应用。
在后台运行
从 Windows 10 版本 1607 开始,应用可以在与应用本身相同的进程中运行后台任务。 使用单个进程模型在后台活动中阅读有关它的详细信息。 本文不会介绍进程内后台处理,但这如何影响应用生命周期,即在应用处于后台时,已添加两个新事件。 它们是:EnteredBackground 和 LeavingBackground。
这些事件还反映用户是否可以查看应用的 UI。
在后台运行是应用程序启动、激活或恢复到的默认状态。 在此状态下,应用程序 UI 尚不可见。
在前台运行
在前台运行意味着应用的 UI 可见。
在应用程序 UI 可见以及进入前台状态运行之前,将触发 LeavingBackground 事件。 当用户切换回应用时,也会触发它。
以前,加载 UI 资产的最佳位置是在“已激活”或“恢复”事件处理程序中。 现在 ,LeavingBackground 是验证 UI 是否已准备就绪的最佳位置。
请务必检查视觉资产目前是否准备就绪,因为这是在应用程序对用户可见之前执行工作的最后机会。 此事件处理程序中的所有 UI 都应快速完成,因为它会影响用户体验的启动和恢复时间。 LeavingBackground 是确保 UI 的第一个帧准备就绪的时间。 然后,应异步处理长时间运行的存储或网络调用,以便事件处理程序可以返回。
当用户离开应用程序时,应用将重新进入后台状态的运行。
重新输入背景状态
EnteredBackground 事件指示应用在前台不再可见。 当应用最小化时,桌面 EnteredBackground 会触发;在手机上切换到主屏幕或其他应用时。
减少应用的内存使用量
由于你的应用不再对用户可见,因此这是停止 UI 呈现工作和动画的最佳位置。 可以使用 LeavingBackground 重新开始该工作。
如果要在后台执行工作,这是准备它的地方。 最好检查 MemoryManager.AppMemoryUsageLevel ,如果需要,请减少应用在后台运行时使用的内存量,使应用不会有被系统终止的风险释放资源。
有关更多详细信息,请参阅 当应用移动到后台状态 时减少内存使用量。
保存状态
暂停事件处理程序是保存应用状态的最佳位置。 但是,如果在后台执行工作(例如,使用扩展执行会话或过程内后台任务执行音频播放),则最好从 EnteredBackground 事件处理程序异步保存数据。 这是因为你的应用可以在后台处于较低优先级时终止。 由于应用在这种情况下不会经历挂起状态,因此你的数据将丢失。
在后台活动开始之前,将数据保存在 EnteredBackground 事件处理程序中,确保在用户将应用带回前台时获得良好的用户体验。 可以使用应用程序数据 API 保存数据和设置。 有关详细信息,请参阅存储和检索设置以及其他应用数据。
保存数据后,如果超出内存使用量限制,则可以从内存中释放数据,因为以后可以重新加载数据。 这将释放可供后台活动所需的资产使用的内存。
请注意,如果你的应用正在进行后台活动,它可以从后台状态的运行移动到前台状态的运行,而不会达到挂起的状态。
注意
当用户关闭应用时,可以在 EnteredBackground 事件之前触发 OnSuspending 事件。 在某些情况下, 在应用终止之前,可能不会触发 EnteredBackground 事件。 请务必将数据保存在 OnSuspending 事件处理程序中。
异步工作和延迟
如果在处理程序中进行异步调用,控件会立即从该异步调用返回。 这意味着,即使异步调用尚未完成,执行也可以从事件处理程序返回,并且应用将移动到下一个状态。 在传递给事件处理程序的 EnteredBackgroundEventArgs 对象上使用 GetDeferral 方法,以延迟挂起,直到对返回的 Windows.Foundation.Deferral 对象调用 Complete 方法之后。
延迟不会增加在应用终止之前运行代码所需的时间。 它只会延迟终止,直到调用延迟的 Complete 方法,或最后期限通过(以先到第一者为准)。
如果需要更多时间来保存状态,请调查在应用进入后台状态之前分阶段保存状态的方法,以便在 OnSuspending 事件处理程序中保存更少。 或者,可以请求 ExtendedExecutionSession 以获取更多时间。 但是,不能保证将授予请求,因此最好找到尽量减少保存状态所需的时间。
应用暂停
当用户最小化应用时,Windows 会等待几秒钟,以查看用户是否会切换回应用。 如果未在此时间范围内切换回,并且没有延长执行、后台任务或活动赞助的执行处于活动状态,Windows 将暂停应用。 当锁屏显示时,只要没有扩展的执行会话等在该应用中处于活动状态,应用也会暂停。
当应用暂停时,它将调用 Application.Suspending 事件。 Visual Studio 的 UWP 项目模板为在 App.xaml.cs 中称为 OnSuspending 的这一事件提供处理程序。 应在此处放置代码以保存应用程序状态。
应释放独占资源和文件句柄,以便其他应用在应用暂停时可以访问它们。 独占资源的示例包括相机、I/O 设备、外部设备和网络资源。 显式释放独占资源和文件句柄有助于确保在应用暂停时其他应用可以访问它们。 恢复应用后,它应重新获取其独占资源和文件句柄。
注意截止时间
为了确保快速且响应迅速的设备,必须在挂起事件处理程序中运行代码的时间有限。 它对于每个设备都是不同的,你可以了解它使用名为“截止时间”的 SuspendingOperation 对象的属性。
与 EnteredBackground 事件处理程序一样,如果从处理程序进行异步调用,控件会立即从该异步调用返回。 这意味着,即使异步调用尚未完成,执行也可以从事件处理程序返回,并且应用将移动到暂停状态。 使用 SuspendingOperation 对象上的 GetDeferral 方法(可通过事件参数提供)延迟进入挂起状态,直到对返回的 SuspendingDeferral 对象调用 Complete 方法之后。
如果需要更多时间,可以请求 ExtendedExecutionSession。 但是,不能保证将授予请求,因此最好找到在挂起事件处理程序中最大程度地减少所需时间的方法。
应用终止
当你的应用暂停时,系统会尝试将你的应用及其数据保留在内存中。 但是,如果系统没有资源来将应用保留在内存中,它将终止你的应用。 应用不会收到它们被终止的通知,因此保存应用数据的唯一机会是在 OnSuspending 事件处理程序中。
当应用确定在终止后已激活它时,它应加载保存的应用程序数据,以便应用处于其终止前处于相同的状态。 当用户切换回已终止的挂起应用时,应用应在 OnLaunched 方法中还原其应用程序数据。 系统不会在应用终止时通知应用,因此应用必须在暂停之前保存其应用程序数据并释放独占资源和文件句柄,并在终止后激活应用时还原它们。
有关使用 Visual Studio 进行调试的注释: Visual Studio 阻止 Windows 挂起附加到调试器的应用。 这是允许用户在应用运行时查看 Visual Studio 调试 UI。 调试应用时,可以使用 Visual Studio 将其发送到暂停事件。 请确保“调试位置”工具栏显示出来,然后单击“暂停”图标。
应用恢复
当用户切换到该应用或当设备退出低功率状态时,将恢复挂起的应用。
当应用从 暂停 状态恢复时,它会进入 后台 状态运行,并且系统会还原它离开的应用,使应用看起来就像它一直在运行一样一直运行。 内存中存储的应用数据不会丢失。 因此,大多数应用在恢复时不需要还原状态,尽管它们应重新获取暂停时释放的任何文件或设备句柄,并还原应用暂停时显式释放的任何状态。
应用可能会暂停数小时或几天。 如果应用的内容或网络连接可能已过时,则应在应用恢复时刷新这些连接。 如果应用为 Application.Resuming 事件注册了事件处理程序,则从挂起状态恢复应用时会调用它。 可以刷新此事件处理程序中的应用内容和数据。
如果已暂停的应用被激活以参与应用协定或扩展,它将首先接收恢复事件,然后接收已激活的事件。
如果暂停的应用已终止,则不存在恢复事件,而是使用 ApplicationExecutionState 的 Terminated 调用 OnLaunched()。 由于在应用暂停时保存了状态,因此可以在 OnLaunched()期间还原该状态,以便应用在离开应用时向用户显示。
当应用暂停时,它不会收到注册以接收的任何网络事件。 这些网络事件不是排队的-它们只是错过的。 因此,应用应在恢复时测试网络状态。
请注意,由于恢复事件不是从 UI 线程引发的,因此如果恢复处理程序中的代码与 UI 通信,则必须使用调度程序。 有关如何执行此操作的代码示例,请参阅 从后台线程更新 UI 线程 。
有关一般准则,请参阅 应用暂停和恢复指南。
应用关闭
通常,用户不需要关闭应用,他们可以让 Windows 管理它们。 但是,用户可以选择使用关闭手势或按 Alt+F4 或使用 Windows Phone 上的任务切换器关闭应用。
没有指示用户关闭应用的事件。 当用户关闭应用时,会首先暂停它,以便你有机会保存其状态。 在 Windows 8.1 及更高版本中,用户关闭应用后,应用将从屏幕和切换列表中删除,但未显式终止。
用户关闭行为:如果应用在被用户关闭时需要执行不同于被 Windows 关闭时的操作,你可以使用激活事件处理程序确定应用是被用户还是被 Windows 终止的。 请参阅 ApplicationExecutionState 枚举的参考中 ClosedByUser 和 Terminated 状态的说明。
除非绝对必要,否则我们建议应用不要以编程方式关闭自己。 例如,如果应用检测到内存泄漏,它可以关闭自身以确保用户个人数据的安全性。
应用崩溃
系统崩溃体验旨在让用户尽快恢复其所执行的操作。 不应提供警告对话框或其他通知,因为这会延迟用户。
如果应用崩溃、停止响应或生成异常,则会根据用户的反馈和诊断设置向Microsoft发送问题报告。 有关详细信息,请参阅 Windows 中的诊断、反馈和隐私。 Microsoft向你提供问题报告中的错误数据的子集,以便你可以使用它来改进应用。 你将能够在仪表板的应用的“质量”页中看到此数据。
当用户在应用崩溃后激活应用时,其激活事件处理程序将收到 NotRunning 的 ApplicationExecutionState 值,并应显示其初始 UI 和数据。 崩溃后,不要例行使用用于恢复暂停的应用数据,因为该数据可能已损坏;请参阅应用暂停和恢复指南。
应用删除
当用户删除应用时,将删除该应用及其所有本地数据。 删除应用不会影响存储在常用位置(如文档或图片库)的用户数据。
应用生命周期和 Visual Studio 项目模板
Visual Studio 项目模板中提供了与应用生命周期相关的基本代码。 基本应用处理启动激活,提供一个用于还原应用数据的位置,并在添加任何自己的代码之前显示主 UI。 有关详细信息,请参阅 适用于应用的 C#、VB 和 C++ 项目模板。
关键应用程序生命周期 API
- Windows.ApplicationModel 命名空间
- Windows.ApplicationModel.Activation 命名空间
- Windows.ApplicationModel.Core 命名空间
- Windows.UI.Xaml.Application 类 (XAML)
- Windows.UI.Xaml.Window 类 (XAML)