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

Windows 應用程式 SDK 中的應用程式生命週期 API 會在 Microsoft.Windows.System.Power 命名空間中提供一組電源管理 API。 這些 API 可讓您了解應用程式如何影響裝置的電源狀態,並使應用程式能夠就資源使用情況做出明智的決策。 例如,當裝置依靠電池電源運作時,應用程式可能會使用此 API 來延遲資源密集型後台任務。

電源管理 API 使用類似現有 PowerSettingRegisterNotification 函式的回呼型模型。 使用回調模型將 API 的覆蓋範圍擴展到所有應用程序,包括後台應用程式、無頭應用程式等。

必要條件

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

  1. 下載並安裝最新版的 Windows 應用程式 SDK。 如需詳細資訊,請參閱 開始使用 WinUI
  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);
}