透過延長執行延後應用程式暫停Postpone app suspension with extended execution

本文章將示範如何在您的應用程式暫止時使用延伸執行來延期,以便使應用程式在最小化或在鎖定畫面的情況下仍繼續執行。This article shows you how to use extended execution to postpone when your app is suspended so that it can run while minimized or under the lock screen.

當使用者最小化或離開應用程式時,它會進入暫止狀態。When the user minimizes or switches away from an app it is put into a suspended state. 它的記憶體會保留,但是不會執行程式碼。Its memory is maintained, but its code does not run. 擁有視覺化使用者介面的所有作業系統版本都是這種狀況。This is true across all OS Editions with a visual user interface. 如需有關您的應用程式何時暫止的詳細資訊,請參閱應用程式生命週期For more details about when your app is suspended, see Application Lifecycle.

有許多情況可能讓 App 在使用者瀏覽離開 App 時或將其最小化時繼續執行,而不是將它暫止。There are cases where an app may need to keep running, rather than be suspended, when the user navigates away from the app, or while it is minimized. 例如,即使使用者瀏覽離開以使用其他 App 時,計算 App 的步驟仍需要繼續執行並追蹤步驟。For example, a step counting app needs to keep running and tracking steps even when the user navigates away to use other apps.

如果 App 必須繼續執行,則作業系統必須讓 App 繼續執行,或者 App 可以要求繼續執行。If an app needs to keep running, either the OS can keep it running, or it can request to keep running. 例如在背景播放音訊時,您可以依照背景媒體播放的步驟進行,作業系統就可以讓應用程式執行久一點。For example, when playing audio in the background, the OS can keep an app running longer if you follow these steps for Background Media Playback. 否則,您就必須手動要求更多執行時間。Otherwise, you must manually request more time. 您可取得用來執行背景執行的時間長度可能會有幾分鐘,但是您必須做好準備,才能隨時處理撤銷中的工作階段。The amount of time you may get to perform background execution may be several minutes but you must be prepared to handle the session being revoked at any time. 當 App 在偵錯工具下執行時,這些應用程式週期時間限制會停用。These application lifecycle time constraints are disabled while the app is running under a debugger. 基於這個原因,務必未在偵錯工具下執行,或者使用 Visual Studio 中可用的週期事件時,測試延伸執行及其他工具以延後 App 暫停。For this reason it is important to test Extended Execution and other tools for postponing app suspension while not running under a debugger or by using the Lifecycle Events available in Visual Studio.

建立 ExtendedExecutionSession 來要求更多時間,以便在背景完成作業。Create an ExtendedExecutionSession to request more time to complete an operation in the background. 您建立的 ExtendedExecutionSession 類型是由您建立它時提供的 ExtendedExecutionReason 所決定。The kind of ExtendedExecutionSession you create is determined by the ExtendedExecutionReason that you provide when you create it. 有三個 ExtendedExecutionReason 列舉值:Unspecified、LocationTrackingSavingDataThere are three ExtendedExecutionReason enum values: Unspecified, LocationTracking and SavingData. 只有一個 ExtendedExecutionSession 可隨時要求;已核准的工作階段要求目前正在使用中時嘗試建立另一個工作階段,將會導致例外狀況 0x8007139F 從 ExtendedExecutionSession 建構函式擲回,以表示該群組或資源不在正確的狀態以執行所要求的作業。Only one ExtendedExecutionSession can be requested at any time; attempting to create another session while an approved session request is currently active will cause exception 0x8007139F to be thrown from the ExtendedExecutionSession constructor stating that the group or resource is not in the correct state to perform the requested operation. 請勿使用 ExtendedExecutionForegroundSessionExtendedExecutionForegroundReason;它們需要受限的功能,且無法在存放區應用程式中使用。Do not use ExtendedExecutionForegroundSession and ExtendedExecutionForegroundReason; they require restricted capabilities and are not available for use in Store applications.

在最小化時執行Run while minimized

有兩個案例可以使用延伸執行:There are two cases where extended execution can be used:

  • 在定期前景執行期間的任何時候,當應用程式在執行中的狀態。At any point during regular foreground execution, while the application is in the running state.
  • 在應用程式已經在應用程式的暫停事件處理常式中收到暫停事件之後 (作業系統將把 App 移往暫停狀態)。After the application has received a suspending event (the OS is about to move the app to the suspended state) in the application’s suspending event handler.

這兩個案例的程式碼相同,但是各個案例中應用程式的行為略為不同。The code for these two cases is the same, but the application behaves a little differently in each. 在第一個案例中,應用程式停留在執行中狀態,即使通常會觸發暫停事件 (例如,使用者瀏覽離開應用程式),就會發生。In the first case, the application stays in the running state, even if an event that normally would trigger suspension occurs (for example, the user navigating away from the application). 執行延伸生效時,應用程式將永遠不會收到暫停事件。The application will never receive a suspending event while the execution extension is in effect. 在處置延伸功能時,應用程式再次變成可以暫停。When the extension is disposed, the application becomes eligible for suspension again.

在第二個案例中,如果應用程式轉換到暫停的狀態,它將會在延伸期間保持在暫停狀態。In the second case, if the application is transitioning to the suspended state, it will stay in a suspending state for the period of the extension. 一旦延伸過期之後,應用程式會進入暫停的狀態,而不需要進一步的通知。Once the extension expires, the application enters the suspended state without further notification.

當您建立 ExtendedExecutionSession 時使用 ExtendedExecutionReason.Unspecified 以要求在應用程式移至背景前,針對某些情況 (例如媒體處理、專案編譯或保持網路連線) 給予額外的執行時間。Use ExtendedExecutionReason.Unspecified when you create an ExtendedExecutionSession to request additional time before your app moves into the background for scenarios such as media processing, project compilation, or keeping a network connection alive. 在執行 Windows 10 傳統型版本 (家用版、專業版、企業版和教育版) 的桌面裝置上,這個做法就能使應用程式在最小化時避免進入暫止狀態。On desktop devices running Windows 10 for desktop editions (Home, Pro, Enterprise, and Education), this is the approach to use if an app needs to avoid being suspended while it is minimized.

在啟動長時間執行的作業時要求延長時間,可延後進入暫止中狀態,否則應用程式就會移至背景。Request the extension when starting a long running operation in order to defer the Suspending state transition that otherwise occurs when the app moves into the background. 在桌面裝置上,使用 ExtendedExecutionReason.Unspecified 建立的延伸執行工作階段具有可感知電池的時間限制。On desktop devices, extended execution sessions created with ExtendedExecutionReason.Unspecified have a battery-aware time limit. 如果裝置連接到牆上電源,則延伸執行的時間長度就沒有限制。If the device is connected to wall power, there is no limit to the length of the extended execution time period. 如果裝置使用電池電源,則在背景中延伸執行的時間最多為十分鐘。If the device is on battery power, the extended execution time period can run up to ten minutes in the background.

[依 App 的電池使用情況] 設定中選取 [允許應用程式執行背景工作] 選項時,平板電腦或膝上型電腦使用者可以犧牲電池使用時間來獲得相同的長時間執行。A tablet or laptop user can get the same long running behavior--at the expense of battery life--when the Allow the app to run background tasks option is selected in Battery usage by app settings. (若要在膝上型電腦上尋找此選項,請移至 [設定 > 系統 > 電池 > 電力使用量(依應用程式)] ([) 剩餘的電池電力百分比] 下的連結 > 選取 > 關閉Windows 管理的應用程式 > 選取 [允許應用程式執行背景工作]。(To find this option on a laptop, go to Settings > System > Battery > Battery usage by App (the link under the percent of battery power remaining) > select an app > turn off Managed By Windows > select Allow app to run background tasks.

在所有的作業系統版本上,當裝置進入連線待命模式時,就會停止這種延伸執行工作階段。On all OS editions this kind of extended execution session stops when the device enters Connected Standby. 在執行 Windows 10 行動裝置版的行動裝置上,只要螢幕持續開啟,這種延伸執行工作階段就會一直執行。On mobile devices running Windows 10 Mobile, this kind of extended execution session will run as long as the screen is on. 當螢幕關閉時,裝置會立即嘗試進入低電源的連線待命模式。When the screen turns off, the device immediately attempts to enter the low-power Connected-Standby mode. 在桌面裝置上,如果出現鎖定畫面,此工作階段將會繼續執行。On desktop devices, the session will continue running if the lock screen appears. 當螢幕關閉後,裝置在一段時間內不會進入連線待命模式。The device does not enter Connected Standby for a period of time after the screen turns off. 在 Xbox 作業系統版本上,除非使用者變更預設值,否則裝置會在一個小時後進入連線待命模式。On the Xbox OS Edition, the device enters Connect Standby after one hour unless the user changes the default.

追蹤使用者的位置Track the user's location

當您建立 ExtendedExecutionSession 時,如果您的應用程式必須定期從 GeoLocator 記錄位置,請指定 ExtendedExecutionReason.LocationTrackingSpecify ExtendedExecutionReason.LocationTracking when you create an ExtendedExecutionSession if your app needs to regularly log the location from the GeoLocator. 由於健身追蹤與導航用應用程式必須定期監控使用者位置,因此應使用這個功能。Apps for fitness tracking and navigation that need to regularly monitor the user's location and should use this reason.

只要需要,位置追蹤延伸的執行工作階段便會執行,包括當行動裝置的螢幕鎖定時。A location tracking extended execution session can run as long as needed, including while the screen is locked on a mobile device. 但是,每個裝置上只能執行一個這樣的工作階段。However, there can only be one such session running per device. 位置追蹤的延伸執行工作階段只能在前景中要求,而且應用程式必須處於執行中狀態。A location tracking extended execution session can only be requested in the foreground, and the app must be in the Running state. 如此可確保使用者會察覺此應用程式已開始延伸位置追蹤工作階段。This ensures that the user is aware that the app has initiated an extended location tracking session. 當應用程式在背景時,依然可以透過背景工作或應用程式服務來使用 GeoLocator,而不必要求位置追蹤的延伸執行工作階段。It is still possible to use the GeoLocator while the app is in the background by using a background task, or an app service, without requesting a location tracking extended execution session.

在本機儲存重要資料Save Critical Data Locally

當您建立 ExtendedExecutionSession 時指定 ExtendedExecutionReason.SavingData 可儲存使用者資料,以免應用程式終止之前未儲存資料而發生資料遺失和不愉快的使用者經驗。Specify ExtendedExecutionReason.SavingData when you create an ExtendedExecutionSession to save user data in the case where not saving the data before the app is terminated will result in data loss and a negative user experience.

請勿使用這種工作階段來延長應用程式上傳或下載資料的時間。Don't use this kind of session to extend the lifetime of an app to upload or download data. 如果您必須上傳資料,請要求背景傳輸或是登錄 MaintenanceTrigger,在有 AC 電源時處理傳輸。If you need to upload data, request a background transfer or register a MaintenanceTrigger to handle the transfer when AC power is available. 當應用程式在前景執行並處於執行中狀態,或是在背景執行並處於暫止中狀態時,可以要求 ExtendedExecutionReason.SavingData 延伸執行工作階段。A ExtendedExecutionReason.SavingData extended execution session can be requested either when the app is in the foreground and in the Running state, or in the background and in the Suspending state.

暫止中狀態是應用程式生命週期中,應用程式在終止之前可以執行工作的最後機會。The Suspending state is the last opportunity during the app lifecycle that an app can do work before the app is terminated. ExtendedExecutionReason.SavingDataExtendedExecutionSession 的唯一類型,可在 Suspending 狀態中要求該類型。ExtendedExecutionReason.SavingData is the only type of ExtendedExecutionSession that can be requested in the Suspending state. 請注意,當應用程式處於暫止中狀態時要求 ExtendedExecutionReason.SavingData 延伸執行工作階段可能會產生下列問題。Requesting a ExtendedExecutionReason.SavingData extended execution session while the app is in the Suspending state creates a potential issue that you should be aware of. 如果在處於暫止中狀態時要求延伸執行工作階段,而且使用者要求應用程式重新啟動,則可能需要很長的時間才能啟動。If an extended execution session is requested while in the Suspending state, and the user requests the app be launched again, it may appear to take a long time to launch. 這是因為延伸執行工作階段期間必須先完成,然後舊的應用程式執行個體才可以關閉,而新的應用程式執行個體才可以啟動。This is because the extended execution session time period must complete before the old instance of the app can be closed and a new instance of the app can be launched. 為確保使用者狀態不會遺失,因此必須犧牲啟動效能時間。Launch performance time is sacrificed in order to guarantee that user state is not lost.

要求、處置和撤銷Request, disposal, and revocation

延伸執行工作階段有三個基本互動:要求、處置和撤銷。There are three fundamental interactions with an extended execution session: the request, disposal, and revocation. 以下程式碼片段會提出要求。Making the request is modeled in the following code snippet.

要求Request

var newSession = new ExtendedExecutionSession();
newSession.Reason = ExtendedExecutionReason.Unspecified;
newSession.Revoked += SessionRevoked;
ExtendedExecutionResult result = await newSession.RequestExtensionAsync();

switch (result)
{
    case ExtendedExecutionResult.Allowed:
        DoLongRunningWork();
        break;

    default:
    case ExtendedExecutionResult.Denied:
        DoShortRunningWork();
        break;
}

參閱程式碼範例See code sample

透過作業系統來呼叫 RequestExtensionAsync 檢查,以了解使用者是否已核准應用程式的背景活動,以及系統是否有可用的資源來啟用背景執行。Calling RequestExtensionAsync checks with the operating system to see if the user has approved background activity for the app and whether the system has the available resources to enable background execution. 只有一個工作階段會在任何時候針對 App 核准,導致額外呼叫 RequestExtensionAsync 以致工作階段被拒絕。Only one session will be approved for an app at any time, causing additional calls to RequestExtensionAsync to result in the session being denied.

您可以事先檢查 BackgroundExecutionManager 來判斷 BackgroundAccessStatus,它是決定您的應用程式是否可在背景執行的使用者設定。You can check the BackgroundExecutionManager beforehand to determine the BackgroundAccessStatus, which is the user setting that indicates whether your app can run in the background or not. 若要深入了解這些使用者設定,請參閱背景活動和能源意識 (英文)。To learn more about these user settings see Background Activity and Energy Awareness.

ExtendedExecutionReason 會表示您的應用程式在背景執行的作業。The ExtendedExecutionReason indicates the operation your app is performing in the background. Description 字串是一般人看得懂的字串,說明您的 App 必須執行此作業的原因。The Description string is a human-readable string that explains why your app needs to perform the operation. 這個字串不會向使用者顯示,但可能會在未來的 Windows 版本中提供。This string is not presented to the user, but may be made available in a future release of Windows. 需要 Revoked 事件處理常式,這樣當使用者或系統決定不要繼續在背景執行應用程式時,延伸執行工作階段才可以正常停止。The Revoked event handler is required so that an extended execution session can halt gracefully if the user, or the system, decides that the app can no longer run in the background.

已撤銷Revoked

如果 App 擁有作用中的延伸執行工作階段,而且系統要求停止背景活動,因為前景應用程式需要資源,則此工作階段會被撤銷。If an app has an active extended execution session and the system requires background activity to halt because a foreground application requires the resources, then the session is revoked. 一定要先引發 Revoked 事件處理常式,才能終止延伸執行工作階段期間。An extended execution session time period is never terminated without first firing the Revoked event handler.

當針對 ExtendedExecutionReason.SavingData 延伸執行工作階段引發 Revoked 事件時,應用程式有片刻時間可完成它原本在執行的作業並結束暫止中狀態。When the Revoked event is fired for an ExtendedExecutionReason.SavingData extended execution session, the app has one second to complete the operation it was performing and finish Suspending.

撤銷發生的原因有許多:已達到執行時間限制、已達到背景能源配額,或是必須回收記憶體,好讓使用者在前景開啟新的應用程式。Revocation can occur for many reasons: an execution time limit was reached, a background energy quota was reached, or memory needs to be reclaimed in order for the user to open a new app in the foreground.

以下是 Revoked 事件處理常式的範例:Here is an example of a Revoked event handler:

private async void SessionRevoked(object sender, ExtendedExecutionRevokedEventArgs args)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        switch (args.Reason)
        {
            case ExtendedExecutionRevokedReason.Resumed:
                rootPage.NotifyUser("Extended execution revoked due to returning to foreground.", NotifyType.StatusMessage);
                break;

            case ExtendedExecutionRevokedReason.SystemPolicy:
                rootPage.NotifyUser("Extended execution revoked due to system policy.", NotifyType.StatusMessage);
                break;
        }

        EndExtendedExecution();
    });
}

參閱程式碼範例See code sample

處置Dispose

最後一個步驟為處置延伸執行工作階段。The final step is to dispose of the extended execution session. 您應該處置工作階段及其他任何耗用大量記憶體的資產,否則應用程式在等候工作階段關閉時所使用的能源將會不利於應用程式的能源配額。You want to dispose of the session, and any other memory intensive assets, because otherwise the energy used by the app while it is waiting for the session to close will be counted against the app's energy quota. 為了盡量保留多一點的能源配額給應用程式使用,當您完成工作階段的工作時一定要處置工作階段,這樣應用程式才可以更快移入已暫止狀態。To preserve as much of the energy quota for the app as possible, it is important to dispose of the session when you are done with your work for the session so that the app can move into the Suspended state more quickly.

您應該自行處置工作階段而非等候撤銷活動,這樣可減少應用程式的能源配額使用量。Disposing of the session yourself, rather than waiting for the revocation event, reduces your app's energy quota usage. 這代表在未來的工作階段中,您的應用程式可以在背景執行久一點,因為您將有更多的能源配額。This means that your app will be permitted to run in the background longer in future sessions because you'll have more energy quota available to do so. 您必須維持 ExtendedExecutionSession 物件的參照,直到作業結束為止,這樣才可以呼叫它的 Dispose 方法。You must maintain a reference to the ExtendedExecutionSession object until the end of the operation so that you can call its Dispose method.

處置延伸執行工作階段的程式碼片段如下:A snippet that disposes an extended execution session follows:

void ClearExtendedExecution(ExtendedExecutionSession session)
{
    if (session != null)
    {
        session.Revoked -= SessionRevoked;
        session.Dispose();
        session = null;
    }
}

參閱程式碼範例See code sample

應用程式一次只能有一個 ExtendedExecutionSession 處於作用中狀態。An app can only have one ExtendedExecutionSession active at a time. 許多應用程式使用非同步工作來完成複雜的作業,而這些作業必須存取存放裝置、網路或網路服務等資源。Many apps use asynchronous tasks in order to complete complex operations that require access to resources such as storage, network, or network-based services. 如果某項作業要求完成多個非同步工作,則必須考量每一項工作的狀態,然後才能處置 ExtendedExecutionSession 並允許暫止應用程式。If an operation requires multiple asynchronous tasks to complete, then the state of each of these tasks must be accounted for before disposing the ExtendedExecutionSession and allowing the app to be suspended. 參照必須算出依然在執行中而且未處置工作階段的數量,直到該值變成零為止。This requires reference counting the number of tasks that are still running, and not disposing of the session until that value reaches zero.

以下為在延伸執行工作階段期間用於管理多個工作的範例程式碼:Here is some example code for managing multiple tasks during an extended execution session period. 如需有關如何在您的 App 中使用這個的詳細資訊,請參閱下列連結的程式碼範例:For more information on how to use this in your app please see the code sample linked below:

static class ExtendedExecutionHelper
{
    private static ExtendedExecutionSession session = null;
    private static int taskCount = 0;

    public static bool IsRunning
    {
        get
        {
            if (session != null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    public static async Task<ExtendedExecutionResult> RequestSessionAsync(ExtendedExecutionReason reason, TypedEventHandler<object, ExtendedExecutionRevokedEventArgs> revoked, String description)
    {
        // The previous Extended Execution must be closed before a new one can be requested.       
        ClearSession();

        var newSession = new ExtendedExecutionSession();
        newSession.Reason = reason;
        newSession.Description = description;
        newSession.Revoked += SessionRevoked;

        // Add a revoked handler provided by the app in order to clean up an operation that had to be halted prematurely
        if(revoked != null)
        {
            newSession.Revoked += revoked;
        }

        ExtendedExecutionResult result = await newSession.RequestExtensionAsync();

        switch (result)
        {
            case ExtendedExecutionResult.Allowed:
                session = newSession;
                break;
            default:
            case ExtendedExecutionResult.Denied:
                newSession.Dispose();
                break;
        }
        return result;
    }

    public static void ClearSession()
    {
        if (session != null)
        {
            session.Dispose();
            session = null;
        }

        taskCount = 0;
    }

    public static Deferral GetExecutionDeferral()
    {
        if (session == null)
        {
            throw new InvalidOperationException("No extended execution session is active");
        }

        taskCount++;
        return new Deferral(OnTaskCompleted);
    }

    private static void OnTaskCompleted()
    {
        if (taskCount > 0)
        {
            taskCount--;
        }
        
        //If there are no more running tasks than end the extended lifetime by clearing the session
        if (taskCount == 0 && session != null)
        {
            ClearSession();
        }
    }

    private static void SessionRevoked(object sender, ExtendedExecutionRevokedEventArgs args)
    {
        //The session has been prematurely revoked due to system constraints, ensure the session is disposed
        if (session != null)
        {
            session.Dispose();
            session = null;
        }
        
        taskCount = 0;
    }
}

參閱程式碼範例See code sample

確認應用程式正常使用資源Ensure that your app uses resources well

調整應用程式的記憶體與能源使用量很重要,這樣一來當您的應用程式不再是前景應用程式時,作業系統仍將允許它繼續執行。Tuning your app's memory and energy use is key to ensuring that the operating system will allow your app to continue to run when it is no longer the foreground app. 使用記憶體管理 API 來了解您的應用程式正在使用多少記憶體。Use the Memory Management APIs to see how much memory your app is using. 您的應用程式使用的記憶體越多,當有另一個應用程式在前景時,作業系統就越難讓您的應用程式繼續執行。The more memory your app uses, the harder it is for the OS to keep your app running when another app is in the foreground. 最終是由使用者控制您的應用程式可執行的所有背景活動,而且他也能看到您的應用程式對電池使用量的影響。The user is ultimately in control of all background activity that your app can perform and has visibility on the impact your app has on battery use.

使用 BackgroundExecutionManager.RequestAccessAsync 可判斷使用者是否已決定限制您的應用程式的背景活動。Use BackgroundExecutionManager.RequestAccessAsync to determine if the user has decided that your app’s background activity should be limited. 請留意您的電池使用量,並且只在需要完成使用者想要的動作時才在背景執行。Be aware of your battery usage and only run in the background when it is necessary to complete an action that the user wants.

另請參閱See also

延伸執行範例Extended Execution Sample
應用程式生命週期Application Lifecycle
應用程式生命週期-透過背景工作和延伸執行 讓應用程式保持運作背景記憶體管理App Lifecycle - Keep Apps Alive with Background Tasks and Extended Execution Background Memory Management
背景傳輸Background Transfers
電池感知和背景活動Battery Awareness and Background Activity
MemoryManager 類別MemoryManager class
在背景播放媒體Play Media in the Background