Ser produtivo no segundo plano - tarefas em segundo plano

Em minha postagem anterior (Continuar produtivo quando seu aplicativo não está sendo exibido na tela), expliquei o modelo de segundo plano do Windows 8 e como seu aplicativo pode ser produtivo quando não está na tela, com eficiência no consumo de energia. Na postagem de hoje, falarei sobre as tarefas em segundo plano e como o seu aplicativo pode executar código em segundo plano, mesmo que esteja suspenso. Descreverei dois cenários comuns com código de exemplo que mostram como executar o código do seu aplicativo em segundo plano, baixando email POP a cada 15 minutos com um aplicativo habilitado para tela de bloqueio, e como qualquer aplicativo pode trabalhar em segundo plano quando o dispositivo está usando energia AC.

Introdução

Os gatilhos de tarefas em segundo plano foram projetados para diversos cenários e aplicativos, por isso possuem diferentes requisitos e restrições de gerenciamento de recursos. Alguns gatilhos de tarefas em segundo plano foram projetados para aplicativos que sempre precisam estar atualizados (por exemplo, email, VOIP), enquanto outros são para cenários mais oportunos (por exemplo, executar uma tarefa de manutenção em AC ou quando algumas condições do sistema são alteradas). Os aplicativos que sempre precisam estar atualizados devem estar na tela de bloqueio, que é limitada a sete aplicativos. Falarei a respeito mais adiante nesta postagem. No entanto, se você quiser executar um trabalho oportuno, qualquer aplicativo pode usar o gatilho maintenance executado em energia AC ou alguns gatilhos do sistema. Para usar esses gatilhos, o aplicativo não precisa estar na tela de bloqueio. Os aplicativos na tela de bloqueio possuem restrições de gerenciamento de recursos mais flexíveis porque precisam ser executados com maior frequência (é por isso que limitamos o número e colocamos o usuário no controle!). Falarei sobre esses detalhes posteriormente.

Você não precisará usar tarefas em segundo plano se quiser apenas manter o conteúdo do aplicativo atualizado. Sempre é possível usar blocos dinâmicos ou notificações agendadas, como explicamos na postagem Criando uma fantástica experiência com o bloco. Depois dessa introdução, vamos mergulhar no código!

Trabalhando em segundo plano quando o dispositivo está usando energia AC

Como vimos nas postagens anteriores, às vezes, o aplicativo precisa de seu próprio código para fornecer funcionalidade em segundo plano. Por exemplo, digamos que você deseja adicionar todas as fotos da Biblioteca de Imagens ao banco de dados do seu aplicativo ou processá-las de alguma forma (por exemplo, gerar miniaturas). Você pode fazer isso quando seu aplicativo for executado em primeiro plano e interagir com o usuário ou pode usar tarefas em segundo plano com um gatilho maintenance executado em segundo plano apenas quando o dispositivo usar energia AC. O gatilho maintenance está disponível para todos e o aplicativo não precisa estar na tela de bloqueio. A vantagem de usar uma tarefa em segundo plano de gatilho maintenance é garantir que ela não interfira na atividade do usuário e só seja executada com energia AC. Assim você não precisa se preocupar com o uso excessivo da bateria.

Este exemplo de código mostra que a tarefa em segundo plano maintenance chama a classe ProcessPictures para processar os arquivos quando é executada. A tarefa é executada a cada 8 horas para procurar novos arquivos a serem processados. A tarefa em segundo plano também registra um manipulador de cancelamento porque as tarefas em segundo plano de manutenção são canceladas quando o dispositivo muda a energia da bateria. No manipulador de cancelamento, o processamento dos arquivos é cancelado. Se você não retornar do manipulador de cancelamento em 5 segundos, o Windows o encerrará o aplicativo. Observe que estes exemplos de código supõem o conhecimento das classes de gatilho e da tarefa em segundo plano. Para obter mais informações sobre essas classes, consulte a documentação do namespace Windows.ApplicationModel.Background no Centro de Desenvolvimento.

C#
 public sealed class MaintenanceBackgroundTask: IBackgroundTask
{
    private ProcessPictures processPic; 
 
    public MaintenanceBackgroundTask()
    {
        // Code to process the pictures 
processPic = new ProcessPictures(); 
    }

    //Main Run method which is activated every 8 hours
   async void IBackgroundTask.Run(IBackgroundTaskInstance taskInstance)
    {
        taskInstance.Canceled += taskInstance_Canceled;

// Because these methods are async, you must use a deferral 
        // to wait for all of them to complete
        BackgroundTaskDeferral deferral = taskInstance.GetDeferral(); 
        List<StorageFile> list = new List<StorageFile>();
        int count = await processPic.EnumerateFiles(list);
        bool retval = await processPic.ProcessFiles(list); 
        
        deferral.Complete(); 
    }

    // Cancel handler, called whenever the task is canceled
    void taskInstance_Canceled(IBackgroundTaskInstance sender, 
            BackgroundTaskCancellationReason reason)
    {
        // Device is now on DC power, cancel processing of files 
        processPic.Cancel = true; 
    }
}

 

JavaScript
 // This JS lives within maintenanceBackgroundTask.js
var processPic = new processPictures();
var count = 0;
var retval = false;

function onCanceled(cancelSender, cancelReason) {
    // Device is now on DC power, cancel processing of files
    processPic.cancel = true;
}
backgroundTaskInstance.addEventListener("canceled", onCanceled);

var list = [];
processPic.enumerateFiles(list).then(function (value) {
    count = value;
    processPic.processFiles(list).then(function (value) {
        retval = value;
// Call close() to indicate the task is complete when 
// all async methods have completed
        close();
    });
});

                   

Este exemplo de código mostra como registrar a tarefa em segundo plano maintenance no aplicativo principal. A tarefa em segundo plano é iniciada a cada 8 horas para processar as imagens na Biblioteca de Documentos e Imagens. Quando não for mais preciso realizar esse trabalho, você poderá cancelar o registro da tarefa em segundo plano usando o método Unregister da classe IBackgroundTaskRegistration.

C#
 //Registering the maintenance trigger background task       
private bool RegisterMaintenanceBackgroundTask()
        {
            BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
            builder.Name = "Maintenance background task"; 
            builder.TaskEntryPoint = "MaintenanceTask.MaintenaceBackgroundTask";
            // Run every 8 hours if the device is on AC power 
            IBackgroundTrigger trigger = new MaintenanceTrigger(480, false);
            builder.SetTrigger(trigger); 
            IBackgroundTaskRegistration task = builder.Register(); 

            return true;
        }

 

JavaScript
 function registerMaintenanceBackgroundTask() 
{
    var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();
    builder.name = "Maintenance background task";
    builder.taskEntryPoint = "js\\maintenanceBackgroundTask.js";
    //Run every 8 hours if the device is on AC power
    var trigger = new Windows.ApplicationModel.Background.MaintenanceTrigger(480, false);
    builder.setTrigger(trigger);
    var task = builder.register();

    return true;
}

Você deve declarar Tarefas em segundo plano no manifesto do aplicativo. Comece abrindo o manifesto do aplicativo no Visual Studio e, na guia Declarações, adicione as declarações Tarefas em segundo plano no menu suspenso. Escolha o tipo de tarefa apropriado e especifique o ponto de entrada (nome da classe da tarefa em segundo plano) ou a página inicial, se você estiver usando uma tarefa em segundo plano JavaScript.

Declarações de manifesto de tarefa em segundo plano 
Figura 1 - Declarações de manifesto de tarefa em segundo plano

Para exibir o conteúdo do manifesto, clique com o botão direito nele e selecione Exibir Código. Tenha em mente que a tarefa maintenance só pode ser executada no host fornecido pelo sistema (backgroundTaskHost.exe ou wwahost.exe para JavaScript) e, portanto, não é possível especificar nenhum atributo Executable. O tipo de tarefa do gatilho Maintenance é systemEvent, como você pode ver no trecho de código do manifesto aqui.

 <Extension Category="windows.backgroundTasks" EntryPoint="MaintenanceTask.MaintenaceBackgroundTask">
         <BackgroundTasks>
           <Task Type="systemEvent" />
         </BackgroundTasks>
       </Extension>

Em JavaScript, EntryPoint é substituído por um atributo StartPage.

 <Extension Category="windows.backgroundTasks" StartPage="js\maintenaceBackgroundTask.js">

Para obter mais informações usando as tarefas em segundo plano, consulte o white paper Introdução às tarefas em segundo plano e o Centro de Desenvolvimento para uso da API.

Baixar email POP a cada 15 minutos

Neste exemplo, precisamos que o aplicativo seja executado de forma previsível e com frequência em segundo plano. Para conseguir isso, coloque o aplicativo na tela de bloqueio.

Como os aplicativos usam as tarefas em segundo plano para sempre permanecerem atualizados mesmo quando o usuário não está usando o dispositivo com Windows 8, o usuário controla os aplicativos que podem usar essas tarefas concedendo-lhes permissão para aparecer na tela de bloqueio. Isso acontece naturalmente porque a tela de bloqueio foi criada para fornecer informações ao usuário sobre os aplicativos sem que ele tenha de desbloquear o dispositivo com Windows 8. Essa relação é bilateral: o aplicativo só pode usar esse tipo de tarefa em segundo plano quando estiver na tela de bloqueio e, da mesma forma, ele só pode aparecer na tela de bloqueio se solicitar o uso desse tipo de tarefa em segundo plano.

background2_img2

Figura 2 - Interface do usuário de personalização de tela de bloqueio e aplicativos habilitados para tela de bloqueio

Como um número relativamente pequeno de aplicativos pode ser colocado na tela de bloqueio, é importante que o aplicativo forneça uma boa experiência de tela de bloqueio. Caso contrário, os usuários o removerão para liberar espaço para outra coisa. Exemplos de aplicativos que se encaixam nesse molde são os de comunicação, por exemplo, um aplicativo de email que mostre uma contagem de mensagens de email não lidas, um aplicativo de calendário que mostre os próximos compromissos no programa de status detalhado ou um aplicativo de mensagens que mostre quantas mensagens o usuário perdeu. Para obter mais informações sobre a tela de bloqueio inclusive mais detalhes sobre o que torna uma aplicativo um bom candidato para aparecer nela, visite o Centro de Desenvolvimento.

Usando o gatilho time para baixar email a cada 15 minutos

Este código de exemplo mostra como registrar uma tarefa em segundo plano do gatilho time que seja executada a cada 15 minutos quando a Internet estiver disponível usando a classe BackgroundTaskBuilder. Se a Internet não estiver disponível, a tarefa em segundo não será executada. Em vez disso, ela aguardará até que ela fique disponível e será executada automaticamente. Esse é outro recurso útil de tarefas em segundo plano que evita um trabalho desnecessário e preserva a duração da bateria do dispositivo. Sem essa condição, o código do aplicativo teria de ser executado, detectar que não há conectividade de rede e emitir um erro porque não conseguiu baixar o email. O email será baixado quer o aplicativo esteja em primeiro plano ou não. Ele também será baixado se o dispositivo estiver no modo Em espera conectado.

C#
 private bool RegisterTimeTriggerBackgroundTask()
        {
            BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
            builder.Name = "Pop mail background task";
            builder.TaskEntryPoint = "MailClient.PopMailBackgroundTask";
            // Run every 15 minutes if the device has internet connectivity
            IBackgroundTrigger trigger = new TimeTrigger(15, false);
            builder.SetTrigger(trigger);
            IBackgroundCondition condition = 
                new SystemCondition(SystemConditionType.InternetAvailable);
            builder.AddCondition(condition); 
            IBackgroundTaskRegistration task = builder.Register();

            return true;
        }
JavaScript
 function registerTimeTriggerBackgroundTask() 
   {
       var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();
       builder.name = "Pop mail background task";
       builder.taskEntryPoint = "js\\popMailBackgroundTask.js";
       //Run every 15 minutes if the device has internet connectivity
       var trigger = new Windows.ApplicationModel.Background.TimeTrigger(15, false);
       builder.setTrigger(trigger);
       var condition = new Windows.ApplicationModel.Background.SystemCondition(                             
Windows.ApplicationModel.Background.SystemConditionType.internetAvailable);
       builder.addCondition(condition);
       var task = builder.register();

       return true;
   }

O gatilho time está disponível apenas para aplicativos na tela de bloqueio, conforme descrito anteriormente. Para solicitar a colocação de forma programática na tela de bloqueio, é necessário usar a classe BackgroundExecutionManager. Se o usuário não colocar o seu aplicativo na tela de bloqueio, as tarefas em segundo plano não serão executadas. Nesse caso, pode ser necessário retornar usando uma tarefa em segundo plano que não exija a tela de bloqueio ou que realize o trabalho quando o usuário executar o seu aplicativo. Para que os usuários não sejam consultados repetidamente, o sistema consulta o usuário apenas uma vez. Se eles disserem não e quiserem adicioná-la mais tarde, poderão fazê-lo manualmente.

C#
 public async Task<bool> ObtainLockScreenAccess()
        {
            BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync();
            
            if (status == BackgroundAccessStatus.Denied || status == BackgroundAccessStatus.Unspecified)
            {
                return false; 
            }

            return true; 
        }

 

JavaScript
 function obtainLockScreenAccess()
   {
       Windows.ApplicationModel.Background.BackgroundExecutionManager.requestAccessAsync().then(function (status) {
           if (status === Windows.ApplicationModel.Background.BackgroundAccessStatus.denied || 
               status === Windows.ApplicationModel.Background.BackgroundAccessStatus.unspecified){
               return false;
           }
           return true;
       });
   }

Este exemplo de código mostra a principal tarefa em segundo plano que baixa email a cada 15 minutos. Ele não entra em detalhes descrevendo como atualizar os blocos e notificações do seu aplicativo, conforme abordado anteriormente na postagem do blog Criando uma fantástica experiência com o bloco.

C#
 void IBackgroundTask.Run(IBackgroundTaskInstance taskInstance)
        {
            int count = popmailClient.GetNewMails(); 
            // Update badge on lock screen with the mail count 
            popmailClient.UpdateLockScreenBadgeWithNewMailCount(count);

            IList<string> mailheaders = popmailClient.GetNewMailHeaders(); 
            // Update app tile with the subjects of the email 
            popmailClient.UpdateTileWithSubjects(mailheaders); 
        }

 

JavaScript
 //This JS lives within popMailBackgroundTask.js
    var count = popmailClient.getNewMails();
    // Update badge on lock screen with the mail count
    popmailClient.updateLockScreenBadgeWithNewmailCount(count);

    var mailheaders = popmailClient.getnewMailHeaders();
    // Update app tile with the subjects of the email
    popmailClient.updatetileWithSubjects(mailheaders);
    close();

Para adicionar o seu aplicativo à tela de bloqueio, é preciso especificar o tipo de notificação da tela de bloqueio disponível na guia Interface do Usuário do Aplicativo do manifesto.

Figura 3 - Declarações de manifesto de tarefa em segundo plano

Este trecho de código é de um manifesto (gerado pelo assistente) de um aplicativo que precisa estar na tela de bloqueio e exibir notificações do sistema na tela de bloqueio. O gatilho time só pode ser executado no host fornecido pelo sistema (backgroundTaskHost.exe ou wwahost.exe para JavaScript) e, portanto, não é possível especificar nenhum atributo Executable. O tipo de tarefa é timer, como você pode ver no manifesto.

 <LockScreen Notification="badgeAndTileText" BadgeLogo="Images\badgelogo.png" />
      <DefaultTile ShowName="allLogos" WideLogo="Images\tile-sdk.png" ShortName="LockScreen CS" />
      <SplashScreen Image="Images\splash-sdk.png" BackgroundColor="#FFFFFF" />
    </VisualElements>
    <Extensions>
      <Extension Category="windows.backgroundTasks" EntryPoint="MailClient.PopMailBackgroundTask">
        <BackgroundTasks>
          <Task Type="timer" />
        </BackgroundTasks>
      </Extension>

Em JavaScript, EntryPoint é substituído por um atributo StartPage.

 <Extension Category="windows.backgroundTasks" StartPage="js\popMailBackgroundTask.js"

 

Cenários avançados

É possível criar aplicativos de VOIP, mensagem instantânea ou email de envio por push mais avançados usando outros gatilhos de tarefa em segundo plano, como Control Channel ou Push Notification. Seu uso está além do escopo desta postagem e você pode obter mais informações a respeito no white paper Rede em segundo plano.

Gerenciamento de recursos para tarefas em segundo plano

Como já mencionamos, as tarefas em segundo plano foram criadas tendo em mente o consumo eficiente de energia e, por isso, possuem restrições de uso de recursos de rede e CPU. Isso evita que um aplicativo em segundo plano esgote a bateria do dispositivo sem que o usuário perceba. Se um aplicativo estiver ativo e o usuário interagir com ele no primeiro plano, nenhuma restrição de uso de recursos da rede e da CPU será aplicada às tarefas em segundo plano do aplicativo.

Restrições de recursos da CPU

Cada aplicativo na tela de bloqueio recebe 2 segundos de tempo da CPU a cada 15 minutos, que podem ser usados por todas as tarefas em segundo plano do aplicativo. Depois de 15 minutos, cada aplicativo na tela de bloqueio recebe mais 2 segundos de tempo da CPU para serem usados pelas tarefas em segundo plano. Todo tempo da CPU não utilizado no intervalo de 15 minutos é perdido e o aplicativo não pode acumulá-lo. Cada aplicativo na tela de bloqueio recebe 1 segundo de tempo da CPU a cada 2 horas. Se o aplicativo usar todo o tempo disponível da CPU, as tarefas em segundo plano serão suspensas até que a cota de aplicativos da CPU seja reabastecida na próxima geração de atualizações de cota da CPU.

O tempo de uso da CPU refere-se à quantidade real da CPU usada pelo aplicativo e não ao tempo do relógio da tarefa em segundo plano. Por exemplo, se a tarefa em segundo plano estiver aguardando em seu código a resposta do servidor remoto e não estiver usando a CPU, o tempo de espera não é contado na cota da CPU.

Restrições de recursos da CPU de tarefas em segundo plano

 

Cota de recursos da CPU

Tempo de atualização

Aplicativo habilitado para tela de bloqueio

2 segundos da CPU

15 minutos

Aplicativo não habilitado para tela de bloqueio

1 segundo da CPU

2 horas

Restrições de recursos da rede

O uso da rede pode representar um gasto significativo da bateria de um dispositivo e também é limitado durante a execução da tarefa em segundo plano. Mas se um dispositivo estiver usando energia AC, as tarefas em segundo plano não serão limitadas pela rede. O uso da CPU para uma tarefa em segundo plano será sempre com restrição de recursos, se o dispositivo estiver usando energia AC.

Esta tabela caracteriza a taxa de transferência de dados da rede para uma rede WiFi com restrição de recursos, supondo uma interferência mínima.

 

Pool global

Mesmo com a cota atribuída para cada aplicativo, às vezes essas restrições de recursos fixas podem não ser suficientes. Para essas situações, existe um pool global compartilhado do qual os aplicativos podem solicitar recursos da rede e da CPU.

Detalhes sobre tarefas em segundo plano, o pool global, suas restrições de gerenciamento de recursos e as práticas recomendadas estão disponíveis no white paper Introdução às tarefas em segundo plano. Ele também inclui um projeto de amostra com fonte.

Resumo

Então a resposta para a pergunta: "o meu aplicativo pode trabalhar quando não está na tela?" é definitivamente sim. O modelo de segundo plano do Windows 8 permite que seu aplicativo execute os principais cenários de usuário final, como downloads de arquivos, reprodução de áudio, atualização de email no segundo plano ou execução de tarefas de manutenção, quando o dispositivo usar energia AC. E, como a plataforma monitora atentamente essas atividades, o trabalho em segundo plano terá um impacto mínimo na resposta do aplicativo em primeiro plano ou na duração da bateria do dispositivo.

Para obter informações técnicas mais detalhadas sobre o modelo de segundo plano do Windows 8, visite o Centro de Desenvolvimento e consulte os diversos white papers. Se você tiver alguma dúvida, não hesite em postá-la aqui nos comentários que tentaremos respondê-la da melhor forma possível.

-- Hari Pulapaka, Gerente de programas, Windows.

Agradecemos a Jake Sabulsky, Johnny Bregar, Kyle Beck e Suhail Khalid por suas contribuições e a muitos outros por seus comentários valiosos, entre eles Alexander Corradini, Arun Kishan, Ben Srour, Ian LeGrow, Jamie Schwartz e John Sheehan.

Recursos

Link

Tipo

Destaques

Introdução às tarefas em segundo plano

White paper

Introdução às tarefas em segundo plano

Namespace da API do modelo de segundo plano

Documentos

Namespace da API do modelo de segundo plano

Exemplo de projeto de tarefas em segundo plano

Exemplo de projeto

Demonstra o uso de tarefas em segundo plano

Visão geral da tela de bloqueio

Documentação conceitual

Explica a tela de bloqueio e as práticas recomendadas

Rede em segundo plano

White paper

Mostra como desenvolver aplicativos avançados, como VOIP, mensagens instantâneas, usando tarefas em segundo plano.

Criando uma fantástica experiência com o bloco

Postagem do blog

Mostra como criar uma ótima experiência com blocos