使用應用程式生命週期 API 進行電源管理

Windows 應用程式 SDK 中的應用程式生命週期 API 會在 Microsoft.Windows.System.Power 命名空間中提供一組電源管理 API。 這些 API 可讓您瞭解應用程式如何影響裝置的電源狀態,並讓應用程式能夠針對資源使用量做出智慧決策。 例如,當裝置在電池電源上執行時,應用程式可能會使用此 API 來延後耗用大量資源的背景工作。

電源管理 API 使用類似現有 PowerSettingRegisterNotification 函式的回呼型模型。 使用回呼模型會將API的觸達範圍延伸至所有應用程式,包括背景應用程式、無頭部應用程式及其他應用程式。

必要條件

若要在 Windows 應用程式 SDK 中使用應用程式生命週期 API:

  1. 下載並安裝最新版的 Windows 應用程式 SDK。 如需詳細資訊,請參閱安裝 Windows 應用程式 SDK 的工具。
  2. 請依照指示建立您的第一個 WinUI 3 專案,或使用現有專案中的 Windows 應用程式 SDK。

訂閱和回應事件

下列範例示範如何訂閱和回應 PowerManager 事件。 此程式代碼會在 啟動期間訂閱 BatteryStatusChanged 事件。 然後,應用程式會檢查目前的電源等級並適當調整其資源使用量,以響應變更。 例如,如果電池在低功率狀態下出電,應用程式可能會延遲任何非關鍵背景工作。

注意

只要應用程式繼續執行,應用程式隨時都可以註冊和取消註冊這些事件,但大部分的應用程式都會想要在中 WinMain 設定回呼。

BOOL bWorkInProgress;
winrt::event_token batteryToken;
winrt::event_token powerToken;
winrt::event_token powerSourceToken;
winrt::event_token chargeToken;
winrt::event_token dischargeToken;

void RegisterPowerManagerCallbacks()
{
    batteryToken = PowerManager::BatteryStatusChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnBatteryStatusChanged(); });
    powerToken = PowerManager::PowerSupplyStatusChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnPowerSupplyStatusChanged(); });
    powerSourceToken = PowerManager::PowerSourceKindChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnPowerSourceKindChanged(); });
    chargeToken = PowerManager::RemainingChargePercentChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnRemainingChargePercentChanged(); });
    dischargeToken = PowerManager::RemainingDischargeTimeChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnRemainingDischargeTimeChanged(); });

    if (batteryToken && powerToken && powerSourceToken && chargeToken && dischargeToken)
    {
        OutputMessage(L"Successfully registered for state notifications");
    }
    else
    {
        OutputMessage(L"Failed to register for state notifications");
    }
}

void OnBatteryStatusChanged()
{
    const size_t statusSize = 16;
    WCHAR szStatus[statusSize];
    wmemset(&(szStatus[0]), 0, statusSize);

    BatteryStatus batteryStatus = PowerManager::BatteryStatus();
    int remainingCharge = PowerManager::RemainingChargePercent();
    switch (batteryStatus)
    {
    case BatteryStatus::Charging:
        wcscpy_s(szStatus, L"Charging");
        break;
    case BatteryStatus::Discharging:
        wcscpy_s(szStatus, L"Discharging");
        break;
    case BatteryStatus::Idle:
        wcscpy_s(szStatus, L"Idle");
        break;
    case BatteryStatus::NotPresent:
        wcscpy_s(szStatus, L"NotPresent");
        break;
    }

    OutputFormattedMessage(
        L"Battery status changed: %s, %d%% remaining", 
        szStatus, remainingCharge);
    DetermineWorkloads();
}

void OnPowerSupplyStatusChanged()
{
//...etc
}

根據多個狀態值設定應用程式邏輯

PowerManager 事件相對較低,而且在某些情況下,呼叫的單一事件處理程式可能無法提供足夠的資訊給應用程式來決定其行為。 在此範例中 ,當裝置與電源中斷連線時,可以呼叫 PowerSupplyStatusChanged 事件。 在此情況下,應用程式必須先檢查目前的電池狀態,才能決定如何繼續。

void DetermineWorkloads()
{
    BatteryStatus batteryStatus = PowerManager::BatteryStatus();
    int remainingCharge = PowerManager::RemainingChargePercent();
    PowerSupplyStatus powerStatus = PowerManager::PowerSupplyStatus();
    PowerSourceKind powerSource = PowerManager::PowerSourceKind();

    if ((powerSource == PowerSourceKind::DC 
        && batteryStatus == BatteryStatus::Discharging 
        && remainingCharge < 25)
        || (powerSource == PowerSourceKind::AC
        && powerStatus == PowerSupplyStatus::Inadequate))
    {
        // The device is not in a good battery/power state, 
        // so we should pause any non-critical work.
        PauseNonCriticalWork();
    }
    else if ((batteryStatus != BatteryStatus::Discharging && remainingCharge > 75)
        && powerStatus != PowerSupplyStatus::Inadequate)
    {
        // The device is in good battery/power state,
        // so let's kick of some high-power work.
        StartPowerIntensiveWork();
    }
}

檢查畫面狀態

PowerManager 類別提供與應用程式電源使用量相關的其他裝置狀態相關信息。 例如,當裝置的顯示器關閉時,應用程式可以停用圖形處理。

void OnDisplayStatusChanged()
{
    const size_t statusSize = 16;
    WCHAR szStatus[statusSize];
    wmemset(&(szStatus[0]), 0, statusSize);

    DisplayStatus displayStatus = PowerManager::DisplayStatus();
    switch (displayStatus)
    {
    case DisplayStatus::Dimmed:
        wcscpy_s(szStatus, L"Dimmed");
        break;
    case DisplayStatus::Off:
        wcscpy_s(szStatus, L"Off");
        break;
    case DisplayStatus::On:
        wcscpy_s(szStatus, L"On");
        break;
    }

    OutputFormattedMessage(
        L"Display status changed: %s", szStatus);
    if (displayStatus == DisplayStatus::Off)
    {
        // The screen is off, let's stop rendering foreground graphics,
        // and instead kick off some background work now.
        StopUpdatingGraphics();
        StartDoingBackgroundWork();
    }
}

取消訂閱事件

應用程式可以在其生命週期中註冊和取消註冊通知。 如果您的應用程式在整個生命週期內不需要接收電源狀態通知,請使用您語言慣用的事件註冊管理系統。

void UnregisterPowerManagerCallbacks()
{
    OutputMessage(L"Unregistering state notifications");
    PowerManager::BatteryStatusChanged(batteryToken);
    PowerManager::PowerSupplyStatusChanged(powerToken);
    PowerManager::PowerSourceKindChanged(powerSourceToken);
    PowerManager::RemainingChargePercentChanged(chargeToken);
    PowerManager::RemainingDischargeTimeChanged(dischargeToken);
}