Поделиться через


Приостановка приложения (DirectX и C++)

В этом разделе показано, как сохранить важные системные состояния и данные приложения при приостановке приложения DirectX универсальная платформа Windows (UWP).

Регистрация обработчика событий приостановки

Сначала зарегистрируйтесь для обработки события CoreApplication::Suspending , которое возникает при перемещении приложения в приостановленное состояние пользователем или системным действием.

Добавьте этот код в реализацию метода IFrameworkView::Initialize поставщика представлений:

void App::Initialize(CoreApplicationView^ applicationView)
{
  //...
  
    CoreApplication::Suspending +=
        ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);

  //...
}

Сохраните все данные приложения перед приостановкой

Когда приложение обрабатывает событие CoreApplication::Suspending , оно может сохранить важные данные приложения в функции обработчика. Приложение должно использовать API хранилища LocalSettings , чтобы сохранить простые данные приложения синхронно. Если вы разрабатываете игру, сохраните все критически важные сведения о состоянии игры. Не забудьте приостановить обработку звука!

Теперь реализуйте обратный вызов. Сохраните данные приложения в этом методе.

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 секунд для сохранения данных, приложение автоматически приостановлено.

Этот обратный вызов происходит как сообщение о событии, обработанное CoreDispatcher для coreWindow приложения. Этот обратный вызов не будет вызываться, если вы не вызываете CoreDispatcher::P rocessEvents из основного цикла приложения (реализовано в методе 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);
        }
    }
}

Обрезка вызовов()

Начиная с Windows 8.1 все приложения UWP DirectX должны вызывать 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 , оно также может освободить эксклюзивные ресурсы и дескриптор файлов. Явным образом освобождает эксклюзивные ресурсы и дескриптор файлов, чтобы другие приложения могли обращаться к ним, пока приложение не использует их. Когда приложение активируется после завершения, он должен открыть свои эксклюзивные ресурсы и дескриптор файлов.

Замечания

Система приостанавливает приложение всякий раз, когда пользователь переключается на другое приложение или на рабочий стол. Система возобновляет работу приложения всякий раз, когда пользователь переключается на него. Когда система возобновляет работу приложения, содержимое переменных и структур данных совпадает с тем, что было до того, как система приостановила приложение. Система восстанавливает приложение точно там, где оно осталось, чтобы он отображался пользователю, как если бы он работал в фоновом режиме.

Система пытается сохранить приложение и его данные в памяти во время приостановки. Однако если в системе нет ресурсов для хранения приложения в памяти, система завершит работу приложения. Когда пользователь переключается обратно на приостановленное приложение, которое было завершено, система отправляет активированное событие и должно восстановить данные приложения в обработчике для события CoreApplicationView::Activated.

Система не уведомляет приложение о завершении работы, поэтому приложение должно сохранить свои данные приложения и освободить эксклюзивные ресурсы и дескриптор файлов при приостановке и восстановить их после активации приложения.