Compartir a través de


Aplazar la suspensión de aplicaciones con ejecución ampliada

En este artículo se muestra cómo usar la ejecución extendida para posponer cuándo se suspende la aplicación para que se pueda ejecutar mientras se minimiza o está bajo la pantalla de bloqueo.

Cuando el usuario minimiza o se aleja de una aplicación, se coloca en un estado suspendido. Su memoria se mantiene, pero su código no se ejecuta. Esto es cierto en todas las ediciones del sistema operativo con una interfaz de usuario visual. Para obtener más información sobre cuándo se suspende la aplicación, consulta Ciclo de vida de la aplicación.

Hay casos en los que es posible que una aplicación tenga que seguir ejecutándose, en lugar de suspenderse, cuando el usuario se aleja de la aplicación o mientras se minimiza. Por ejemplo, una aplicación de recuento de pasos debe seguir ejecutándose y siguiendo los pasos incluso cuando el usuario se desplaza para usar otras aplicaciones.

Si una aplicación necesita seguir ejecutándose, el sistema operativo puede mantenerlo en ejecución o puede solicitar que siga ejecutándose. Por ejemplo, al reproducir audio en segundo plano, el sistema operativo puede mantener una aplicación ejecutándose más tiempo si sigue estos pasos para Reproducción multimedia en segundo plano. De lo contrario, debe solicitar manualmente más tiempo. La cantidad de tiempo que puede llegar a realizar la ejecución en segundo plano puede ser de varios minutos, pero debe estar preparado para controlar la sesión que se revoca en cualquier momento. Estas restricciones de tiempo de ciclo de vida de la aplicación están deshabilitadas mientras la aplicación se ejecuta en un depurador. Por este motivo, es importante probar la ejecución extendida y otras herramientas para posponer la suspensión de la aplicación mientras no se ejecuta en un depurador o mediante los eventos de ciclo de vida disponibles en Visual Studio.

Cree una extendedExecutionSession para solicitar más tiempo para completar una operación en segundo plano. El tipo de ExtendedExecutionSession que cree viene determinado por extendedExecutionReason que se proporciona al crearlo. Hay tres valores de enumeración ExtendedExecutionReason : Unspecified, LocationTracking y SavingData. Solo se puede solicitar una ExtendedExecutionSession en cualquier momento; si intenta crear otra sesión mientras una solicitud de sesión aprobada está activa, se producirá una excepción 0x8007139F iniciarse desde el constructor ExtendedExecutionSession que indica que el grupo o recurso no está en el estado correcto para realizar la operación solicitada. No use ExtendedExecutionForegroundSession y ExtendedExecutionForegroundReason; requieren funcionalidades restringidas y no están disponibles para su uso en las aplicaciones de La Tienda.

Ejecutar mientras se minimiza

Hay dos casos en los que se puede usar la ejecución extendida:

  • En cualquier momento durante la ejecución en primer plano normal, mientras la aplicación está en estado en ejecución.
  • Una vez que la aplicación ha recibido un evento de suspensión (el sistema operativo está a punto de mover la aplicación al estado suspendido) en el controlador de eventos de suspensión de la aplicación.

El código de estos dos casos es el mismo, pero la aplicación se comporta un poco de forma diferente en cada uno. En el primer caso, la aplicación permanece en estado de ejecución, incluso si se produce un evento que normalmente desencadenaría la suspensión (por ejemplo, el usuario se aleja de la aplicación). La aplicación nunca recibirá un evento de suspensión mientras la extensión de ejecución está en vigor. Cuando se elimina la extensión, la aplicación vuelve a ser apta para la suspensión.

En el segundo caso, si la aplicación realiza la transición al estado suspendido, permanecerá en un estado de suspensión durante el período de la extensión. Una vez expirada la extensión, la aplicación entra en estado suspendido sin ninguna notificación adicional.

Usa ExtendedExecutionReason.Unspecified cuando creas una ExtendedExecutionSession para solicitar tiempo adicional antes de que la aplicación pase a segundo plano para escenarios como el procesamiento multimedia, la compilación del proyecto o mantener activa una conexión de red. En los dispositivos de escritorio que ejecutan Windows 10 para ediciones de escritorio (Home, Pro, Enterprise y Education), este es el enfoque que se debe usar si una aplicación necesita evitar suspenderse mientras se minimiza.

Solicite la extensión al iniciar una operación de larga duración para aplazar la transición de estado suspendiendo que, de lo contrario, se produce cuando la aplicación se mueve en segundo plano. En los dispositivos de escritorio, las sesiones de ejecución extendidas creadas con ExtendedExecutionReason.Unspecified tienen un límite de tiempo compatible con la batería. Si el dispositivo está conectado a la alimentación de pared, no hay ningún límite durante el período de tiempo de ejecución extendido. Si el dispositivo está encendido con batería, el período de tiempo de ejecución extendido puede ejecutarse hasta diez minutos en segundo plano.

Un usuario de tableta o portátil puede obtener el mismo comportamiento de larga duración, a costa de la duración de la batería, cuando la opción Permitir que la aplicación ejecute tareas en segundo plano está seleccionada en Uso de batería por configuración de la aplicación . (Para encontrar esta opción en un portátil, vaya a Configuración Uso>de batería de batería del sistema>>por aplicación (el vínculo bajo el porcentaje de energía de la batería restante) > seleccione una aplicación > desactivaDa por Windows> seleccione Permitir que la aplicación ejecute tareas en segundo plano.

En todas las ediciones del sistema operativo, este tipo de sesión de ejecución extendida se detiene cuando el dispositivo entra en espera conectada. En dispositivos móviles que ejecutan Windows 10 Mobile, este tipo de sesión de ejecución extendida se ejecutará siempre que la pantalla esté activada. Cuando la pantalla se apaga, el dispositivo intenta entrar inmediatamente en el modo connected-standby de bajo consumo. En los dispositivos de escritorio, la sesión continuará ejecutándose si aparece la pantalla de bloqueo. El dispositivo no escribe El modo de espera conectado durante un período de tiempo después de que la pantalla se apague. En xbox OS Edition, el dispositivo escribe Connect Standby después de una hora a menos que el usuario cambie el valor predeterminado.

Seguimiento de la ubicación del usuario

Especifique ExtendedExecutionReason.LocationTracking al crear una ExtendedExecutionSession si la aplicación necesita registrar regularmente la ubicación desde GeoLocator. Las aplicaciones para el seguimiento de fitness y la navegación que necesitan supervisar regularmente la ubicación del usuario y deben usar este motivo.

Una sesión de ejecución extendida de seguimiento de ubicación puede ejecutarse siempre que sea necesario, incluido mientras la pantalla está bloqueada en un dispositivo móvil. Sin embargo, solo puede haber una sesión de este tipo que se ejecute por dispositivo. Una sesión de ejecución extendida de seguimiento de ubicación solo se puede solicitar en primer plano y la aplicación debe estar en estado En ejecución . Esto garantiza que el usuario tenga en cuenta que la aplicación ha iniciado una sesión de seguimiento de ubicación extendida. Todavía es posible usar GeoLocator mientras la aplicación está en segundo plano mediante una tarea en segundo plano o un servicio de aplicaciones, sin solicitar una sesión de ejecución extendida de seguimiento de ubicación.

Guardar datos críticos localmente

Especifique ExtendedExecutionReason.SavingData al crear una extendedExecutionSession para guardar los datos de usuario en caso de que no guarde los datos antes de que finalice la aplicación provocará la pérdida de datos y una experiencia de usuario negativa.

No use este tipo de sesión para ampliar la duración de una aplicación para cargar o descargar datos. Si necesita cargar datos, solicite una transferencia en segundo plano o registre un MaintenanceTrigger para controlar la transferencia cuando la alimentación de CA esté disponible. Se puede solicitar una sesión de ejecución extendida ExtendedExecutionReason.SavingData cuando la aplicación está en primer plano y en el estado En ejecución, o en segundo plano y en estado Suspending .

El estado Suspending es la última oportunidad durante el ciclo de vida de la aplicación que una aplicación puede hacer trabajo antes de que finalice la aplicación. ExtendedExecutionReason.SavingData es el único tipo de ExtendedExecutionSession que se puede solicitar en el estado Suspending . Solicitar una sesión de ejecución extendida ExtendedExecutionReason.SavingData mientras la aplicación está en estado Suspending crea un posible problema que debe tener en cuenta. Si se solicita una sesión de ejecución extendida mientras se encuentra en el estado Suspending y el usuario solicita que la aplicación se inicie de nuevo, puede tardar mucho tiempo en iniciarse. Esto se debe a que el período de tiempo de la sesión de ejecución extendida debe completarse antes de que se pueda cerrar la instancia anterior de la aplicación y se pueda iniciar una nueva instancia de la aplicación. El tiempo de rendimiento del inicio se sacrifica para garantizar que el estado del usuario no se pierda.

Solicitud, eliminación y revocación

Hay tres interacciones fundamentales con una sesión de ejecución extendida: la solicitud, la eliminación y la revocación. La realización de la solicitud se modela en el siguiente fragmento de código.

Solicitar

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;
}

Consulte el ejemplo de código.

Al llamar a RequestExtensionAsync , se comprueba con el sistema operativo para ver si el usuario ha aprobado la actividad en segundo plano de la aplicación y si el sistema tiene los recursos disponibles para habilitar la ejecución en segundo plano. Solo se aprobará una sesión para una aplicación en cualquier momento, lo que hará que se denieguen llamadas adicionales a RequestExtensionAsync .

Puedes comprobar el BackgroundExecutionManager de antemano para determinar backgroundAccessStatus, que es la configuración de usuario que indica si la aplicación puede ejecutarse en segundo plano o no. Para obtener más información sobre esta configuración de usuario, consulte Actividad en segundo plano y Reconocimiento de energía.

ExtendedExecutionReason indica la operación que realiza la aplicación en segundo plano. La cadena Description es una cadena legible que explica por qué la aplicación debe realizar la operación. Esta cadena no se presenta al usuario, pero puede estar disponible en una versión futura de Windows. El controlador de eventos revocado es necesario para que una sesión de ejecución extendida pueda detenerse correctamente si el usuario, o el sistema, decide que la aplicación ya no se puede ejecutar en segundo plano.

Revocada

Si una aplicación tiene una sesión de ejecución extendida activa y el sistema requiere que se detenga la actividad en segundo plano porque una aplicación en primer plano requiere los recursos, se revoca la sesión. Un período de tiempo de sesión de ejecución extendida nunca finaliza sin desencadenar primero el controlador de eventos Revocado .

Cuando se desencadena el evento Revoked para una sesión de ejecución extendida ExtendedExecutionReason.SavingData , la aplicación tiene un segundo para completar la operación que estaba realizando y finalizando suspendiendo.

La revocación puede producirse por muchas razones: se alcanzó un límite de tiempo de ejecución, se alcanzó una cuota de energía en segundo plano o es necesario reclamar memoria para que el usuario abra una nueva aplicación en primer plano.

Este es un ejemplo de un controlador de eventos revocado:

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();
    });
}

Consulte el ejemplo de código.

Dispose

El último paso es eliminar la sesión de ejecución extendida. Quiere eliminar la sesión y cualquier otro recurso de uso intensivo de memoria, ya que, de lo contrario, la energía usada por la aplicación mientras está esperando a que se cierre la sesión se contará con la cuota de energía de la aplicación. Para conservar la mayor parte de la cuota de energía de la aplicación, es importante eliminar la sesión cuando haya terminado con el trabajo de la sesión para que la aplicación pueda pasar al estado Suspendido más rápidamente.

La eliminación de la sesión usted mismo, en lugar de esperar al evento de revocación, reduce el uso de la cuota de energía de la aplicación. Esto significa que la aplicación podrá ejecutarse en segundo plano durante más tiempo en sesiones futuras, ya que tendrá más cuota de energía disponible para hacerlo. Debe mantener una referencia al objeto ExtendedExecutionSession hasta el final de la operación para que pueda llamar a su método Dispose .

Un fragmento de código que elimina una sesión de ejecución extendida a continuación:

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

Consulte el ejemplo de código.

Una aplicación solo puede tener una ExtendedExecutionSession activa a la vez. Muchas aplicaciones usan tareas asincrónicas para completar operaciones complejas que requieren acceso a recursos como almacenamiento, red o servicios basados en red. Si una operación requiere que se completen varias tareas asincrónicas, se debe tener en cuenta el estado de cada una de estas tareas antes de eliminar ExtendedExecutionSession y permitir que la aplicación se suspenda. Esto requiere hacer referencia al recuento del número de tareas que todavía se están ejecutando y no eliminar la sesión hasta que ese valor alcance cero.

Este es un ejemplo de código para administrar varias tareas durante un período de sesión de ejecución extendido. Para obtener más información sobre cómo usar esto en la aplicación, consulte el ejemplo de código vinculado a continuación:

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;
    }
}

Consulte el ejemplo de código.

Asegúrese de que la aplicación usa bien los recursos.

Ajustar la memoria y el uso de energía de la aplicación es clave para asegurarse de que el sistema operativo permitirá que la aplicación continúe ejecutándose cuando ya no sea la aplicación en primer plano. Use las API de administración de memoria para ver la cantidad de memoria que usa la aplicación. Cuanto más memoria usa la aplicación, más difícil es que el sistema operativo mantenga la aplicación en ejecución cuando otra aplicación esté en primer plano. En última instancia, el usuario tiene el control de toda la actividad en segundo plano que la aplicación puede realizar y tiene visibilidad sobre el impacto que tiene la aplicación en el uso de la batería.

Usa BackgroundExecutionManager.RequestAccessAsync para determinar si el usuario ha decidido que la actividad en segundo plano de la aplicación debe estar limitada. Tenga en cuenta el uso de la batería y ejecute solo en segundo plano cuando sea necesario completar una acción que el usuario desee.

Consulte también

Ejemplo de ejecución extendida
Ciclo de vida de aplicación
Ciclo de vida de la aplicación: mantener las aplicaciones activas con tareas en segundo plano y administración de memoria en segundo plano de ejecuciónextendida
Transferencias en segundo plano
Reconocimiento de la batería y actividad en segundo plano
Clase MemoryManager
Reproducir contenido multimedia en segundo plano