Adiar a suspensão do aplicativo com execução estendida

Este artigo mostra como usar a execução estendida para adiar quando seu aplicativo é suspenso para que ele possa ser executado enquanto minimizado ou na tela de bloqueio.

Quando o usuário minimiza ou sai de um aplicativo, ele é colocado em um estado suspenso. Sua memória é mantida, mas seu código não é executado. Isso é verdade em todas as edições do sistema operacional com uma interface de usuário visual. Para obter mais detalhes sobre quando seu aplicativo é suspenso, consulte Ciclo de vida do aplicativo.

Há casos em que um aplicativo pode precisar continuar em execução, em vez de ser suspenso, quando o usuário sai do aplicativo ou enquanto ele está minimizado. Por exemplo, um aplicativo de contagem de passos precisa continuar em execução e rastrear etapas mesmo quando o usuário sai para usar outros aplicativos.

Se um aplicativo precisar continuar em execução, o sistema operacional poderá mantê-lo em execução ou poderá solicitar que continue em execução. Por exemplo, ao reproduzir áudio em segundo plano, o sistema operacional pode manter um aplicativo em execução por mais tempo se você seguir estas etapas para Reprodução de mídia em segundo plano. Caso contrário, você deve solicitar manualmente mais tempo. A quantidade de tempo que você pode obter para executar a execução em segundo plano pode ser de vários minutos, mas você deve estar preparado para lidar com a sessão que está sendo revogada a qualquer momento. Essas restrições de tempo do ciclo de vida do aplicativo são desabilitadas enquanto o aplicativo está em execução em um depurador. Por esse motivo, é importante testar a Execução Estendida e outras ferramentas para adiar a suspensão do aplicativo enquanto não estiver em execução em um depurador ou usando os Eventos de Ciclo de Vida disponíveis no Visual Studio.

Crie uma ExtendedExecutionSession para solicitar mais tempo para concluir uma operação em segundo plano. O tipo de ExtendedExecutionSession que você cria é determinado pelo ExtendedExecutionReason que você fornece ao criá-lo. Há três valores de enumeração ExtendedExecutionReason : Unspecified, LocationTracking e SavingData. Apenas um ExtendedExecutionSession pode ser solicitado a qualquer momento; tentar criar outra sessão enquanto uma solicitação de sessão aprovada estiver ativa no momento fará com que 0x8007139F de exceção sejam lançados do construtor ExtendedExecutionSession informando que o grupo ou recurso não está no estado correto para executar a operação solicitada. Não use ExtendedExecutionForegroundSession e ExtendedExecutionForegroundReason; eles exigem recursos restritos e não estão disponíveis para uso em aplicativos da Store.

Executar enquanto minimizado

Há dois casos em que a execução estendida pode ser usada:

  • A qualquer momento durante a execução regular em primeiro plano, enquanto o aplicativo está no estado de execução.
  • Depois que o aplicativo receber um evento de suspensão (o sistema operacional está prestes a mover o aplicativo para o estado suspenso) no manipulador de eventos de suspensão do aplicativo.

O código para esses dois casos é o mesmo, mas o aplicativo se comporta de maneira um pouco diferente em cada um. No primeiro caso, o aplicativo permanece no estado de execução, mesmo que ocorra um evento que normalmente dispararia a suspensão (por exemplo, o usuário navegando para fora do aplicativo). O aplicativo nunca receberá um evento de suspensão enquanto a extensão de execução estiver em vigor. Quando a extensão é descartada, o pedido torna-se elegível para suspensão novamente.

No segundo caso, se o aplicativo estiver em transição para o estado suspenso, ele permanecerá em um estado suspenso durante o período da extensão. Depois que a extensão expirar, o aplicativo entrará no estado suspenso sem notificação adicional.

Use ExtendedExecutionReason.Unspecified ao criar um ExtendedExecutionSession para solicitar tempo adicional antes que seu aplicativo seja movido para o segundo plano para cenários como processamento de mídia, compilação de projeto ou manutenção de uma conexão de rede ativa. Em dispositivos de área de trabalho que executam Windows 10 para edições da área de trabalho (Home, Pro, Enterprise e Education), essa é a abordagem a ser usada se um aplicativo precisar evitar ser suspenso enquanto estiver minimizado.

Solicite a extensão ao iniciar uma operação de execução longa para adiar a transição de estado de suspensão que, de outra forma, ocorre quando o aplicativo é movido para o segundo plano. Em dispositivos de desktop, as sessões de execução estendida criadas com ExtendedExecutionReason.Unspecified têm um limite de tempo com reconhecimento de bateria. Se o dispositivo estiver conectado à alimentação da parede, não há limite para a duração do período de tempo de execução estendido. Se o dispositivo estiver com bateria, o período de tempo de execução estendido pode ser executado em até dez minutos em segundo plano.

Um usuário de tablet ou laptop pode obter o mesmo comportamento de execução prolongada, às custas da vida útil da bateria, quando a opção Permitir que o aplicativo execute tarefas em segundo plano é selecionada em Uso da bateria por configurações do aplicativo . (Para encontrar essa opção em um laptop, vá para Configurações>Sistema>Bateria>Uso da bateria por aplicativo (o link abaixo da porcentagem de energia restante da bateria) > selecione um aplicativo > desative Gerenciado pelo Windows> selecione Permitir que o aplicativo execute tarefas em segundo plano.

Em todas as edições do sistema operacional, esse tipo de sessão de execução estendida é interrompida quando o dispositivo entra no modo de espera conectado. Em dispositivos móveis que executam o Windows 10 Mobile, esse tipo de sessão de execução estendida será executado enquanto a tela estiver ligada. Quando a tela desliga, o dispositivo tenta imediatamente entrar no modo de espera conectado de baixo consumo de energia. Em dispositivos desktop, a sessão continuará em execução se a tela de bloqueio for exibida. O dispositivo não entra no modo de espera conectado por um período de tempo depois que a tela é desligada. No Xbox OS Edition, o dispositivo entra no Modo de Espera de Conexão após uma hora, a menos que o usuário altere o padrão.

Rastrear a localização do usuário

Especifique ExtendedExecutionReason.LocationTracking ao criar uma ExtendedExecutionSession se seu aplicativo precisar registrar regularmente o local do GeoLocator. Aplicativos para rastreamento e navegação de condicionamento físico que precisam monitorar regularmente a localização do usuário e devem usar esse motivo.

Uma sessão de execução estendida de rastreamento de localização pode ser executada pelo tempo que for necessário, inclusive enquanto a tela estiver bloqueada em um dispositivo móvel. No entanto, só pode haver uma sessão desse tipo em execução por dispositivo. Uma sessão de execução estendida de rastreamento de local só pode ser solicitada em primeiro plano e o aplicativo deve estar no estado Em execução . Isso garante que o usuário esteja ciente de que o aplicativo iniciou uma sessão estendida de rastreamento de localização. Ainda é possível usar o GeoLocator enquanto o aplicativo está em segundo plano usando uma tarefa em segundo plano ou um serviço de aplicativo, sem solicitar uma sessão de execução estendida de rastreamento de localização.

Salve dados críticos localmente

Especifique ExtendedExecutionReason.SavingData ao criar um ExtendedExecutionSession para salvar dados do usuário no caso em que não salvar os dados antes que o aplicativo seja encerrado resultará em perda de dados e uma experiência negativa do usuário.

Não use esse tipo de sessão para estender o tempo de vida de um aplicativo para carregar ou baixar dados. Se você precisar carregar dados, solicite uma transferência em segundo plano ou registre um MaintenanceTrigger para lidar com a transferência quando a energia CA estiver disponível. Uma sessão de execução estendida ExtendedExecutionReason.SavingData pode ser solicitada quando o aplicativo está em primeiro plano e no estado Em execução ou em segundo plano e no estado Suspending.

O estado de suspensão é a última oportunidade durante o ciclo de vida do aplicativo em que um aplicativo pode trabalhar antes de ser encerrado. ExtendedExecutionReason.SavingData é o único tipo de ExtendedExecutionSession que pode ser solicitado no estado Suspending. Solicitar uma sessão de execução estendida ExtendedExecutionReason.SavingData enquanto o aplicativo está no estado Suspending cria um possível problema do qual você deve estar ciente. Se uma sessão de execução estendida for solicitada enquanto estiver no estado Suspenso e o usuário solicitar que o aplicativo seja iniciado novamente, pode parecer que levará muito tempo para iniciar. Isso ocorre porque o período de tempo da sessão de execução estendida deve ser concluído antes que a instância antiga do aplicativo possa ser fechada e uma nova instância do aplicativo possa ser iniciada. O tempo de desempenho de inicialização é sacrificado para garantir que o estado do usuário não seja perdido.

Solicitação, descarte e revogação

Há três interações fundamentais com uma sessão de execução estendida: a solicitação, o descarte e a revogação. Fazer a solicitação é modelado no snippet de código a seguir.

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

Veja o exemplo de código

Chamar RequestExtensionAsync verifica com o sistema operacional se o usuário aprovou a atividade em segundo plano para o aplicativo e se o sistema tem os recursos disponíveis para habilitar a execução em segundo plano. Apenas uma sessão será aprovada para um aplicativo a qualquer momento, fazendo com que chamadas adicionais para RequestExtensionAsync resultem na negação da sessão.

Você pode verificar o BackgroundExecutionManager com antecedência para determinar o BackgroundAccessStatus, que é a configuração do usuário que indica se seu aplicativo pode ser executado em segundo plano ou não. Para saber mais sobre essas configurações do usuário, consulte Atividade em segundo plano e Reconhecimento de energia.

O ExtendedExecutionReason indica a operação que seu aplicativo está executando em segundo plano. A cadeia de caracteres Description é uma cadeia de caracteres legível que explica por que seu aplicativo precisa executar a operação. Essa cadeia de caracteres não é apresentada ao usuário, mas pode ser disponibilizada em uma versão futura do Windows. O manipulador de eventos Revoked é necessário para que uma sessão de execução estendida possa ser interrompida normalmente se o usuário ou o sistema decidir que o aplicativo não pode mais ser executado em segundo plano.

Revogado

Se um aplicativo tiver uma sessão de execução estendida ativa e o sistema exigir que a atividade em segundo plano seja interrompida porque um aplicativo em primeiro plano requer os recursos, a sessão será revogada. Um período de tempo de sessão de execução estendido nunca é encerrado sem primeiro disparar o manipulador de eventos Revoked .

Quando o evento Revoked é acionado para uma sessão de execução estendida ExtendedExecutionReason.SavingData , o aplicativo tem um segundo para concluir a operação que estava executando e concluir a suspensão.

A revogação pode ocorrer por vários motivos: um limite de tempo de execução foi atingido, uma cota de energia em segundo plano foi atingida ou a memória precisa ser recuperada para que o usuário abra um novo aplicativo em primeiro plano.

Aqui está um exemplo de um manipulador de eventos Revoked:

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

Veja o exemplo de código

Descartar

A etapa final é descartar a sessão de execução estendida. Você deseja descartar a sessão e quaisquer outros ativos com uso intensivo de memória, caso contrário, a energia usada pelo aplicativo enquanto aguarda o fechamento da sessão será contada na cota de energia do aplicativo. Para preservar o máximo possível da cota de energia do aplicativo, é importante descartar a sessão quando você terminar o trabalho da sessão para que o aplicativo possa passar para o estado Suspenso mais rapidamente.

Descartar a sessão por conta própria, em vez de aguardar o evento de revogação, reduz o uso da cota de energia do app. Isso significa que seu aplicativo poderá ser executado em segundo plano por mais tempo em sessões futuras, pois você terá mais cota de energia disponível para fazer isso. Você deve manter uma referência ao objeto ExtendedExecutionSession até o final da operação para que possa chamar seu método Dispose .

Um snippet que descarta uma sessão de execução estendida é o seguinte:

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

Veja o exemplo de código

Um aplicativo só pode ter uma ExtendedExecutionSession ativa por vez. Muitos aplicativos usam tarefas assíncronas para concluir operações complexas que exigem acesso a recursos como armazenamento, rede ou serviços baseados em rede. Se uma operação exigir várias tarefas assíncronas para ser concluída, o estado de cada uma dessas tarefas deverá ser considerado antes de descartar o ExtendedExecutionSession e permitir que o aplicativo seja suspenso. Isso requer que a referência conte o número de tarefas que ainda estão em execução e não descarte a sessão até que esse valor chegue a zero.

Aqui está um código de exemplo para gerenciar várias tarefas durante um período de sessão de execução estendido. Para obter mais informações sobre como usar isso em seu aplicativo, consulte o exemplo de código vinculado abaixo:

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

Veja o exemplo de código

Certifique-se de que seu aplicativo use bem os recursos

Ajustar o uso de memória e energia do aplicativo é fundamental para garantir que o sistema operacional permita que seu aplicativo continue a ser executado quando não for mais o aplicativo em primeiro plano. Use as APIs de Gerenciamento de Memória para ver quanta memória seu aplicativo está usando. Quanto mais memória seu aplicativo usar, mais difícil será para o sistema operacional manter seu aplicativo em execução quando outro aplicativo estiver em primeiro plano. Em última análise, o usuário está no controle de todas as atividades em segundo plano que seu aplicativo pode executar e tem visibilidade sobre o impacto que seu aplicativo tem no uso da bateria.

Use BackgroundExecutionManager.RequestAccessAsync para determinar se o usuário decidiu que a atividade em segundo plano do aplicativo deve ser limitada. Esteja ciente do uso da bateria e só execute em segundo plano quando for necessário concluir uma ação que o usuário deseja.

Confira também

Exemplo de execução estendida
Ciclo de vida do aplicativo
Ciclo de vida do aplicativo - Mantenha os aplicativos ativos com tarefas em segundo plano e gerenciamento de memória em segundo plano de execuçãoestendida
Transferências em segundo plano
Reconhecimento da bateria e atividade em segundo plano
Classe MemoryManager
Reproduzir mídia em segundo plano