如何暂停应用(DirectX 和 C++)
本主题介绍了系统在暂停通用 Windows 平台 (UWP) DirectX 应用时,如何保存重要系统状态和应用数据。
注册暂停的事件处理程序
首先,注册以处理 CoreApplication::Suspending 事件,当某个用户或系统操作将你的应用移动到某个已暂停状态时, 会发生此事件。
将此代码添加到你的视图提供程序 的 IFrameworkView::Initialize 方法的实现中:
void App::Initialize(CoreApplicationView^ applicationView)
{
//...
CoreApplication::Suspending +=
ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
//...
}
在暂停之前保存所有应用数据
当你的应用处理 CoreApplication::Suspending 事件时,它将有机会将其重要的应用程序数据保存到处理程序函数中。 应用应该使用 LocalSettings 存储 API 来同步保存简单的应用程序数据。 如果你要开发一个游戏,请保存所有关键游戏状态信息。 请不要忘记去挂起音频处理!
现在,请实施回调。 将应用数据保存在此方法中。
void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
{
// Save app state asynchronously after requesting a deferral. Holding a deferral
// indicates that the application is busy performing suspending operations. Be
// aware that a deferral may not be held indefinitely. After about five seconds,
// the app will be forced to exit.
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
create_task([this, deferral]()
{
m_deviceResources->Trim();
// Insert your code here.
deferral->Complete();
});
}
此回调必须在 5 秒内完成。 在此回调期间,你必须通过调用 SuspendingOperation::GetDeferral 来请求一个延迟,这会启动递减计数。 当你的应用完成保存操作之后,请调用 SuspendingDeferral::Complete 来告知系统你的应用现在已准备好进行挂起。 如果你不请求延迟,或者如果你的应用保存数据所花费的时间超过 5 秒,则会自动暂停你的应用。
对于应用的 CoreWindow,此回调是由 CoreDispatcher 处理的一条事件消息。 如果你没有从你的应用的主回路调用 CoreDispatcher::ProcessEvents(在你的查看提供程序的 IFrameworkView::Run 方法中实现),那么将不会调用此回调。
// This method is called after the window becomes active.
void App::Run()
{
while (!m_windowClosed)
{
if (m_windowVisible)
{
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
m_main->Update();
if (m_main->Render())
{
m_deviceResources->Present();
}
}
else
{
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
}
}
}
调用 Trim()
从 Windows 8.1 开始,所有 DirectX WUP 应用在挂起时必须调用 IDXGIDevice3::Trim。 此调用指示图形驱动程序释放为该应用分配的所有临时缓冲区,这样可以减少应用在暂停状态时被终止以回收内存资源的情况。 这是针对 Windows 8.1 的认证要求。
void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
{
// Save app state asynchronously after requesting a deferral. Holding a deferral
// indicates that the application is busy performing suspending operations. Be
// aware that a deferral may not be held indefinitely. After about five seconds,
// the app will be forced to exit.
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
create_task([this, deferral]()
{
m_deviceResources->Trim();
// Insert your code here.
deferral->Complete();
});
}
// Call this method when the app suspends. It provides a hint to the driver that the app
// is entering an idle state and that temporary buffers can be reclaimed for use by other apps.
void DX::DeviceResources::Trim()
{
ComPtr<IDXGIDevice3> dxgiDevice;
m_d3dDevice.As(&dxgiDevice);
dxgiDevice->Trim();
}
释放所有独占资源和文件句柄
当你的应用处理 CoreApplication::Suspending 事件时,它还将有机会释放独占资源和文件句柄。 显式释放独占资源和文件句柄有助于确保:你的应用未使用它们时其他应用可以访问它们。 当在终止后又激活应用时,它应该打开其独占资源和文件句柄。
注解
每当用户切换到桌面或其他应用时,系统都会挂起你的应用。 每当用户切回到你的应用时,系统就会恢复你的应用。 当系统恢复你的应用时,你的变量和数据结构的内容与系统将你的应用暂停之前的内容相同。 系统会将你的应用完全恢复到你离开时的状态,使用户感觉你的应用好像一直在后台运行一样。
当你的应用暂停时,系统会尝试将你的应用及其数据保留在内存中。 但是,如果系统没有资源将你的应用保存在内存里,则将终止你的应用。 当用户切换回已终止的暂停应用时,系统会发送 Activated 事件,且应该在其处理程序中为 CoreApplicationView::Activated 事件还原其应用程序数据。
当终止应用时系统不会通知应用,因此当暂停应用时,你的应用必须保存其应用程序数据并释放独占资源和文件句柄,并且在终止后又激活应用时还原这些内容。
相关主题