Liberar memoria cuando la aplicación pasa a segundo planoFree memory when your app moves to the background

En este artículo se muestra cómo reducir la cantidad de memoria que usa la aplicación cuando pasa al estado de segundo plano para evitar su suspensión o, posiblemente, su finalización.This article shows you how to reduce the amount of memory that your app uses when it moves to the background state so that it won't be suspended and possibly terminated.

Nuevos eventos de segundo planoNew background events

Windows 10, versión 1607, incorpora dos nuevos eventos de ciclo de vida de aplicación: EnteredBackground y LeavingBackground.Windows 10, version 1607, introduces two new application lifecycle events, EnteredBackground and LeavingBackground. Estos eventos permiten que la aplicación sepa cuándo entra y sale del estado de segundo plano.These events let your app know when it is entering and leaving the background.

Cuando la aplicación pasa al estado de segundo plano, pueden cambiar las restricciones de memoria que aplica el sistema.When your app moves into the background, the memory constraints enforced by the system may change. Usa estos eventos para comprobar el consumo de memoria actual y liberar recursos para permanecer por debajo del límite, de modo que no se suspenda o, tal vez, se finalice la aplicación mientras está en segundo plano.Use these events to check your current memory consumption and free resources in order to stay below the limit so that your app won't be suspended and possibly terminated while it is in the background.

Eventos para controlar el uso de memoria de la aplicaciónEvents for controlling your app's memory usage

El evento MemoryManager.AppMemoryUsageLimitChanging se genera justo antes de que cambie el límite del total de memoria que puede usar la aplicación.MemoryManager.AppMemoryUsageLimitChanging is raised just before the limit of total memory the app can use is changed. Por ejemplo, si la aplicación pasa a segundo plano y en la consola Xbox el límite de memoria cambia de 1024 MB a 128 MB.For example, when the app moves into the background and on the Xbox the memory limit changes from 1024MB to 128MB.
Este es el evento más importante que se debe controlar para evitar que la plataforma suspenda o finalice la aplicación.This is the most important event to handle to keep the platform from suspending or terminating the app.

El evento MemoryManager.AppMemoryUsageIncreased se genera cuando el consumo de memoria de la aplicación ha aumentado a un valor superior en la enumeración AppMemoryUsageLevel.MemoryManager.AppMemoryUsageIncreased is raised when the app's memory consumption has increased to a higher value in the AppMemoryUsageLevel enumeration. Por ejemplo, de Low a Medium.For example, from Low to Medium. Si bien controlar este evento es opcional, se recomienda hacerlo porque la aplicación sigue siendo responsable de mantenerse por debajo del límite.Handling this event is optional but recommended because the application is still responsible for staying under the limit.

El evento MemoryManager.AppMemoryUsageDecreased se genera cuando el consumo de memoria de la aplicación ha disminuido a un valor inferior en la enumeración AppMemoryUsageLevel.MemoryManager.AppMemoryUsageDecreased is raised when the app's memory consumption has decreased to a lower value in the AppMemoryUsageLevel enumeration. Por ejemplo, de High a Low.For example, from High to Low. Controlar este evento es opcional, pero indica que la aplicación puede asignar memoria adicional si es necesario.Handling this event is optional but indicates the application may be able to allocate additional memory if needed.

Controlar la transición entre el primer plano y el segundo planoHandle the transition between foreground and background

Cuando la aplicación pasa de primer plano a segundo plano, se genera el evento EnteredBackground.When your app moves from the foreground to the background, the EnteredBackground event is raised. Cuando la aplicación vuelve al primer plano, se genera el evento LeavingBackground.When your app returns to the foreground, the LeavingBackground event is raised. Puedes registrar controladores para estos eventos cuando creas la aplicación.You can register handlers for these events when your app is created. En la plantilla de proyecto predeterminada, esto se realiza en el constructor de clase App en App.xaml.cs.In the default project template, this is done in the App class constructor in App.xaml.cs.

Dado que la ejecución en segundo plano reducirá los recursos de memoria que la aplicación tiene permitido conservar, también debes registrar los eventos AppMemoryUsageIncreased y AppMemoryUsageLimitChanging, que puedes usar para comprobar el uso actual de memoria de la aplicación y el límite actual.Because running in the background will reduce the memory resources your app is allowed to retain, you should also register for the AppMemoryUsageIncreased and AppMemoryUsageLimitChanging events which you can use to check your app's current memory usage and the current limit. En los siguientes ejemplos se muestran los controladores de estos eventos.The handlers for these events are shown in the following examples. Para obtener más información sobre el ciclo de vida de las aplicaciones para UWP, consulta Ciclo de vida de la aplicación.For more information on the application lifecycle for UWP apps, see App lifecycle.

public App()
{
    this.InitializeComponent();

    this.Suspending += OnSuspending;

    // Subscribe to key lifecyle events to know when the app
    // transitions to and from foreground and background.
    // Leaving the background is an important transition
    // because the app may need to restore UI.
    this.EnteredBackground += AppEnteredBackground;
    this.LeavingBackground += AppLeavingBackground;

    // During the transition from foreground to background the
    // memory limit allowed for the application changes. The application
    // has a short time to respond by bringing its memory usage
    // under the new limit.
    Windows.System.MemoryManager.AppMemoryUsageLimitChanging += MemoryManager_AppMemoryUsageLimitChanging;

    // After an application is backgrounded it is expected to stay
    // under a memory target to maintain priority to keep running.
    // Subscribe to the event that informs the app of this change.
    Windows.System.MemoryManager.AppMemoryUsageIncreased += MemoryManager_AppMemoryUsageIncreased;
}

Cuando se genera el evento EnteredBackground, establece la variable de seguimiento para indicar que actualmente estás ejecutando en segundo plano.When the EnteredBackground event is raised, set the tracking variable to indicate that you are currently running in the background. Esto será útil cuando escribas el código para reducir el uso de memoria.This will be useful when you write the code for reducing memory usage.

/// <summary>
/// The application entered the background.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AppEnteredBackground(object sender, EnteredBackgroundEventArgs e)
{
    _isInBackgroundMode = true;

    // An application may wish to release views and view data
    // here since the UI is no longer visible.
    //
    // As a performance optimization, here we note instead that
    // the app has entered background mode with _isInBackgroundMode and
    // defer unloading views until AppMemoryUsageLimitChanging or
    // AppMemoryUsageIncreased is raised with an indication that
    // the application is under memory pressure.
}

Cuando la aplicación cambia al estado de segundo plano, el sistema reduce el límite de memoria de la aplicación con el fin de garantizar que la aplicación en primer plano actual tenga los recursos suficientes para proporcionar una experiencia del usuario que responda adecuadamente.When your app transitions to the background, the system reduces the memory limit for the app to ensure that the current foreground app has sufficient resources to provide a responsive user experience

El controlador del evento AppMemoryUsageLimitChanging permite a la aplicación saber que la memoria que tiene asignada se ha reducido y proporciona el nuevo límite en los argumentos del evento pasados al controlador.The AppMemoryUsageLimitChanging event handler lets your app know that its allotted memory has been reduced and provides the new limit in the event arguments passed into the handler. Compara la propiedad MemoryManager.AppMemoryUsage, que proporciona el uso actual de la aplicación, con propiedad la NewLimit de los argumentos del evento, que especifica el nuevo límite.Compare the MemoryManager.AppMemoryUsage property, which provides your app's current usage, to the NewLimit property of the event arguments, which specifies the new limit. Si el uso de memoria supera el límite, debes reducir dicho uso de memoria.If your memory usage exceeds the limit, you need to reduce your memory usage.

En este ejemplo, esto se realiza en el método auxiliar ReduceMemoryUsage, que se define más adelante en este artículo.In this example, this is done in the helper method ReduceMemoryUsage, which is defined later in this article.

/// <summary>
/// Raised when the memory limit for the app is changing, such as when the app
/// enters the background.
/// </summary>
/// <remarks>
/// If the app is using more than the new limit, it must reduce memory within 2 seconds
/// on some platforms in order to avoid being suspended or terminated.
///
/// While some platforms will allow the application
/// to continue running over the limit, reducing usage in the time
/// allotted will enable the best experience across the broadest range of devices.
/// </remarks>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MemoryManager_AppMemoryUsageLimitChanging(object sender, AppMemoryUsageLimitChangingEventArgs e)
{
    // If app memory usage is over the limit, reduce usage within 2 seconds
    // so that the system does not suspend the app
    if (MemoryManager.AppMemoryUsage >= e.NewLimit)
    {
        ReduceMemoryUsage(e.NewLimit);
    }
}

Nota

Las configuraciones de algunos dispositivo permitirán que una aplicación siga ejecutándose por encima del nuevo límite de memoria hasta que el sistema sufra presión de recursos, pero las de otros dispositivos no lo permitirán.Some device configurations will allow an application to continue running over the new memory limit until the system experiences resource pressure, and some will not. En concreto, en Xbox, las aplicaciones se suspenderán o finalizarán si no reducen el uso de memoria por debajo de los nuevos límites en un plazo de 2 (dos) segundos.On Xbox, in particular, apps will be suspended or terminated if they do not reduce memory to under the new limits within 2 seconds. Esto significa que puedes ofrecer la mejor experiencia en la gama más amplia de dispositivos mediante el uso de este evento para reducir el uso de recursos por debajo del límite en el plazo de 2 (dos) segundos desde que se genere el evento.This means that you can deliver the best experience across the broadest range of devices by using this event to reduce resource usage below the limit within 2 seconds of the event being raised.

Es posible que, aunque el uso de memoria de la aplicación esté actualmente por debajo del límite de memoria para aplicaciones en segundo plano, cuando cambie por primera vez a segundo plano, pueda aumentar el consumo de memoria con el tiempo y empezar a acercarse al límite.It is possible that although your app's memory usage is currently under the memory limit for background apps when it first transitions to the background, it may increase its memory consumption over time and begin to approach the limit. El controlador del evento AppMemoryUsageIncreased ofrece la posibilidad de comprobar el uso actual cuando aumenta y, si es necesario, liberar memoria.The handler the AppMemoryUsageIncreased provides an opportunity to check your current usage when it increases and, if necessary, free memory.

Comprueba si el valor de AppMemoryUsageLevel es High u OverLimit, y si es así, reduce el uso de memoria.Check to see if the AppMemoryUsageLevel is High or OverLimit, and if so, reduce your memory usage. En este ejemplo, esto se controla con el método auxiliar ReduceMemoryUsage.In this example this is handled by the helper method, ReduceMemoryUsage. También puede suscribirte al evento AppMemoryUsageDecreased, comprobar si la aplicación está por debajo del límite y, si es así, saber que puedes asignar recursos adicionales.You can also subscribe to the AppMemoryUsageDecreased event, check to see if your app is under the limit, and if so then you know you can allocate additional resources.

/// <summary>
/// Handle system notifications that the app has increased its
/// memory usage level compared to its current target.
/// </summary>
/// <remarks>
/// The app may have increased its usage or the app may have moved
/// to the background and the system lowered the target for the app
/// In either case, if the application wants to maintain its priority
/// to avoid being suspended before other apps, it may need to reduce
/// its memory usage.
///
/// This is not a replacement for handling AppMemoryUsageLimitChanging
/// which is critical to ensure the app immediately gets below the new
/// limit. However, once the app is allowed to continue running and
/// policy is applied, some apps may wish to continue monitoring
/// usage to ensure they remain below the limit.
/// </remarks>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MemoryManager_AppMemoryUsageIncreased(object sender, object e)
{
    // Obtain the current usage level
    var level = MemoryManager.AppMemoryUsageLevel;

    // Check the usage level to determine whether reducing memory is necessary.
    // Memory usage may have been fine when initially entering the background but
    // the app may have increased its memory usage since then and will need to trim back.
    if (level == AppMemoryUsageLevel.OverLimit || level == AppMemoryUsageLevel.High)
    {
        ReduceMemoryUsage(MemoryManager.AppMemoryUsageLimit);
    }
}

ReduceMemoryUsage es un método auxiliar que puedes implementar para liberar memoria cuando la aplicación supera el límite de uso mientras se ejecuta en segundo plano.ReduceMemoryUsage is a helper method that you can implement to release memory when your app is over the usage limit while running in the background. La manera de liberar memoria depende de los detalles específicos de la aplicación, pero una forma recomendada es desechar la interfaz de usuario y los demás recursos asociados con la vista de la aplicación.How you release memory depends on the specifics of your app, but one recommended way to free up memory is to dispose of your UI and the other resources associated with your app view. Para ello, comprueba que estés ejecutando en el estado de segundo plano y luego establece la propiedad Content de la ventana de la aplicación en null, anula el registro de los controladores de eventos de la interfaz de usuario y quita todas las referencias que pudieras tener a la página.To do so, ensure that you are running in the background state then set the Content property of your app's window to null and unregister your UI event handlers and remove any other references you may have to the page. Si no logras anular el registro de los controladores de eventos de la interfaz de usuario ni borrar todas las referencias que pudieras tener a la página, no podrás liberar los recursos de la página.Failing to unregister your UI event handlers and clearing any other references you may have to the page will prevent the page resources from being released. A continuación, llama a GC.Collect para recuperar la memoria liberada inmediatamente.Then call GC.Collect to reclaim the freed up memory immediately. Normalmente no se fuerza la recolección de elementos no utilizados porque el sistema se encarga de ello.Typically you don't force garbage collection because the system will take care of it for you. En este caso concreto, se reduce la cantidad de memoria que se carga en esta aplicación, ya que se trata en segundo plano para reducir la probabilidad de que el sistema determine que debe finalizar la aplicación para recuperar memoria.In this specific case, we are reducing the amount of memory charged to this application as it goes into the background to reduce the likelihood that the system will determine that it should terminate the app to reclaim memory.

/// <summary>
/// Reduces application memory usage.
/// </summary>
/// <remarks>
/// When the app enters the background, receives a memory limit changing
/// event, or receives a memory usage increased event, it can
/// can optionally unload cached data or even its view content in
/// order to reduce memory usage and the chance of being suspended.
///
/// This must be called from multiple event handlers because an application may already
/// be in a high memory usage state when entering the background, or it
/// may be in a low memory usage state with no need to unload resources yet
/// and only enter a higher state later.
/// </remarks>
public void ReduceMemoryUsage(ulong limit)
{
    // If the app has caches or other memory it can free, it should do so now.
    // << App can release memory here >>

    // Additionally, if the application is currently
    // in background mode and still has a view with content
    // then the view can be released to save memory and
    // can be recreated again later when leaving the background.
    if (isInBackgroundMode && Window.Current.Content != null)
    {
        // Some apps may wish to use this helper to explicitly disconnect
        // child references.
        // VisualTreeHelper.DisconnectChildrenRecursive(Window.Current.Content);

        // Clear the view content. Note that views should rely on
        // events like Page.Unloaded to further release resources.
        // Release event handlers in views since references can
        // prevent objects from being collected.
        Window.Current.Content = null;
    }

    // Run the GC to collect released resources.
    GC.Collect();
}

Cuando se recopila el contenido de la ventana, cada fotograma comienza su proceso de desconexión.When the window content is collected, each Frame begins its disconnection process. Si hay objetos Page en el árbol de objetos visuales en el contenido de la ventana, iniciarán la generación del evento Unloaded.If there are Pages in the visual object tree under the window content, these will begin firing their Unloaded event. Los objetos Pages no se puede borrar completamente de la memoria, a menos que se eliminen todas las referencias a ellos.Pages cannot be completely cleared from memory unless all references to them are removed. En la devolución de llamada de Unloaded, realiza los siguientes pasos para garantizar que la memoria se libere rápidamente:In the Unloaded callback, do the following to ensure that memory is quickly freed:

  • Borra y establece cualquier estructura de datos de gran tamaño de Page en null.Clear and set any large data structures in your Page to null.
  • Anula el registro de todos los controladores de eventos que tienen métodos de devolución de llamada dentro de Page.Unregister all event handlers that have callback methods within the Page. Asegúrate de registrar esas devoluciones de llamada durante el controlador del evento Loaded correspondiente a Page.Make sure to register those callbacks during the Loaded event handler for the Page. El evento Loaded se genera si la interfaz de usuario se ha reconstituido y el objeto Page se ha agregado al árbol de objetos visuales.The Loaded event is raised when the UI has been reconstituted and the Page has been added to the visual object tree.
  • Llama a GC.Collect al final de la devolución de llamada de Unloaded para efectuar rápidamente la recolección de elementos no utilizados de cualquiera de las estructuras de datos de gran tamaño que estableciste recién en null.Call GC.Collect at the end of the Unloaded callback to quickly garbage collect any of the large data structures you have just set to null. De nuevo, normalmente no fuerza la recolección de elementos no utilizados porque el sistema se encarga de ello.Again, typically you don't force garbage collection because the system will take care of it for you. En este caso concreto, se reduce la cantidad de memoria que se carga en esta aplicación, ya que se trata en segundo plano para reducir la probabilidad de que el sistema determine que debe finalizar la aplicación para recuperar memoria.In this specific case, we are reducing the amount of memory charged to this application as it goes into the background to reduce the likelihood that the system will determine that it should terminate the app to reclaim memory.
private void MainPage_Unloaded(object sender, RoutedEventArgs e)
{
   // << free large data sructures and set them to null, here >>

   // Disconnect event handlers for this page so that the garbage
   // collector can free memory associated with the page
   Window.Current.Activated -= Current_Activated;
   GC.Collect();
}

En el controlador del evento LeavingBackground, establece la variable de seguimiento (isInBackgroundMode) para indicar que la aplicación ya no se ejecuta en segundo plano.In the LeavingBackground event handler, set the tracking variable (isInBackgroundMode) to indicate that your app is no longer running in the background. A continuación, comprueba si el valor de la propiedad Content de la ventana actual es null, que será así si has desechado las vistas de la aplicación para liberar memoria durante la ejecución en segundo plano.Next, check to see if the Content of the current window is null-- which it will be if you disposed of your app views in order to clear up memory while you were running in the background. Si el contenido de la ventana es null, reconstruye la vista de la aplicación.If the window content is null, rebuild your app view. En este ejemplo, el contenido de la ventana se crea en el método auxiliar CreateRootFrame.In this example, the window content is created in the helper method CreateRootFrame.

/// <summary>
/// The application is leaving the background.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AppLeavingBackground(object sender, LeavingBackgroundEventArgs e)
{
    // Mark the transition out of the background state
    _isInBackgroundMode = false;

    // Restore view content if it was previously unloaded
    if (Window.Current.Content == null)
    {
        CreateRootFrame(ApplicationExecutionState.Running, string.Empty);
    }
}

El método auxiliar CreateRootFrame vuelve a crear el contenido de la vista de la aplicación.The CreateRootFrame helper method recreates the view content for your app. El código de este método es casi idéntico al código del controlador OnLaunched proporcionado en la plantilla de proyecto predeterminada.The code in this method is nearly identical to the OnLaunched handler code provided in the default project template. La única diferencia es que el controlador Launching determina el estado de ejecución anterior a partir de la propiedad PreviousExecutionState de la clase LaunchActivatedEventArgs y el método CreateRootFrame simplemente obtiene el estado de ejecución anterior que se pasó como argumento.The one difference is that the Launching handler determines the previous execution state from the PreviousExecutionState property of the LaunchActivatedEventArgs and the CreateRootFrame method simply gets the previous execution state passed in as an argument. Para minimizar el código duplicado, puedes refactorizar el código del controlador de eventos Launching predeterminado para llamar a CreateRootFrame.To minimize duplicated code, you can refactor the default Launching event handler code to call CreateRootFrame.

void CreateRootFrame(ApplicationExecutionState previousExecutionState, string arguments)
{
    Frame rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null)
    {
        // Create a Frame to act as the navigation context and navigate to the first page
        rootFrame = new Frame();

        // Set the default language
        rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

        rootFrame.NavigationFailed += OnNavigationFailed;

        if (previousExecutionState == ApplicationExecutionState.Terminated)
        {
            //TODO: Load state from previously suspended application
        }

        // Place the frame in the current Window
        Window.Current.Content = rootFrame;
    }

    if (rootFrame.Content == null)
    {
        // When the navigation stack isn't restored navigate to the first page,
        // configuring the new page by passing required information as a navigation
        // parameter
        rootFrame.Navigate(typeof(MainPage), arguments);
    }
}

DirectricesGuidelines

Pasar de primer plano a segundo planoMoving from the foreground to the background

Cuando una aplicación pasa de primer plano a segundo plano, el sistema funciona en nombre de la aplicación para liberar los recursos que no son necesarios en segundo plano.When an app moves from the foreground to the background, the system does work on behalf of the app to free up resources that are not needed in the background. Por ejemplo, los marcos de interfaz de usuario vacían las texturas almacenadas en caché y el subsistema de vídeo libera la memoria asignada en nombre de la aplicación.For example, the UI frameworks flush cached textures and the video subsystem frees memory allocated on behalf of the app. Aun así, una aplicación debe supervisar cuidadosamente su uso de memoria para evitar que el sistema la suspenda o la finalice.However, an app will still need to carefully monitor its memory usage to avoid being suspended or terminated by the system.

Cuando una aplicación pasa de primer plano a segundo plano, primero obtiene un evento EnteredBackground y después un evento AppMemoryUsageLimitChanging.When an app moves from the foreground to the background it will first get an EnteredBackground event and then a AppMemoryUsageLimitChanging event.

  • Usa el evento EnteredBackground para liberar los recursos de interfaz de usuario que sabes que la aplicación no necesita mientras se ejecuta en segundo plano.Do use the EnteredBackground event to free up UI resources that you know your app does not need while running in the background. Por ejemplo, podrías liberar la imagen de portada de una canción.For example, you could free the cover art image for a song.
  • Usa el evento MemoryManager.AppMemoryUsageLimitChanging para asegurarte de que la aplicación esté usando menos memoria que el nuevo límite de segundo plano.Do use the AppMemoryUsageLimitChanging event to ensure that your app is using less memory than the new background limit. Si no es así, asegúrate de liberar recursos.Make sure that you free up resources if not. Si no lo haces, puede que se suspenda o finalice la aplicación según la directiva específica del dispositivo.If you do not, your app may be suspended or terminated according to device specific policy.
  • Invoca manualmente el recolector de elementos no utilizados si la aplicación supera el nuevo límite de memoria cuando se genera el evento AppMemoryUsageLimitChanging.Do manually invoke the garbage collector if your app is over the new memory limit when the AppMemoryUsageLimitChanging event is raised.
  • Usa el evento AppMemoryUsageIncreased para seguir supervisando el uso de memoria de la aplicación mientras se ejecuta en segundo plano si esperas que cambie.Do use the AppMemoryUsageIncreased event to continue to monitor your app’s memory usage while running in the background if you expect it to change. Si el valor de AppMemoryUsageLevel es High u OverLimit, asegúrate de liberar recursos.If the AppMemoryUsageLevel is High or OverLimit make sure that you free up resources.
  • Considera liberar recursos de interfaz de usuario en el controlador del evento AppMemoryUsageLimitChanging en lugar de hacerlo en el controlador de EnteredBackground como una optimización del rendimiento.Consider freeing UI resources in the AppMemoryUsageLimitChanging event handler instead of in the EnteredBackground handler as a performance optimization. Usa un valor booleano que se establece los controladores de los eventos EnteredBackground/LeavingBackground para saber si la aplicación está en segundo plano o en primer plano.Use a boolean value set in the EnteredBackground/LeavingBackground event handlers to track whether the app is in the background or foreground. A continuación, en el controlador del evento AppMemoryUsageLimitChanging, si el valor de AppMemoryUsage supera el límite y la aplicación está en segundo plano (según el valor booleano), puedes liberar recursos de interfaz de usuario.Then in the AppMemoryUsageLimitChanging event handler, if AppMemoryUsage is over the limit and the app is in the background (based on the Boolean value) you can free UI resources.
  • No realices operaciones prolongadas en el evento EnteredBackground porque puedes provocar que al usuario la transición entre aplicaciones le parezca lenta.Do not perform long running operations in the EnteredBackground event because you can cause the transition between applications to appear slow to the user.

Pasar de segundo plano a primer planoMoving from the background to the foreground

Cuando una aplicación pasa de segundo plano a primer plano, primero obtiene un evento AppMemoryUsageLimitChanging y después un evento LeavingBackground.When an app moves from the background to the foreground, the app will first get an AppMemoryUsageLimitChanging event and then a LeavingBackground event.

  • No uses el evento LeavingBackground para volver a crear los recursos de interfaz de usuario que la aplicación desechó cuando pasó a segundo plano.Do use the LeavingBackground event to recreate UI resources that your app discarded when moving into the background.