Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Observação
Este artigo aborda tarefas de fundo construídas com a API Windows Runtime (WinRT) BackgroundTaskBuilder no Windows.ApplicationModel.Background espaço de nomes para aplicações com identidade de pacote, incluindo aplicações UWP e de desktop empacotadas. Se estiver a desenvolver uma nova aplicação ou a migrar uma aplicação existente para o SDK de Aplicações Windows, consulte Utilizar tarefas em segundo plano em aplicações Windows e Estratégia de migração de tarefas em segundo plano.
Aprenda a criar e registar uma tarefa em segundo plano na sua aplicação com a classe Windows Runtime (WinRT) BackgroundTaskBuilder.
Registrar uma tarefa em segundo plano
Consulte o exemplo BackgroundTask para um exemplo completo de registo de uma tarefa em segundo plano numa aplicação Plataforma Universal do Windows (UWP).
O exemplo seguinte mostra o registo de uma tarefa COM do Win32 que corre com um temporizador recorrente de 15 minutos.
Para registar uma tarefa em segundo plano, deve primeiro criar uma nova instância da classe BackgroundTaskBuilder . A BackgroundTaskBuilder classe é usada para criar e registar tarefas em segundo plano na sua aplicação. O seguinte exemplo de código demonstra como criar uma nova instância da BackgroundTaskBuilder classe:
using System;
using Windows.ApplicationModel.Background;
public IBackgroundTaskRegistration RegisterBackgroundTaskWithSystem(IBackgroundTrigger trigger, Guid entryPointClsid, string taskName)
{
BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
builder.SetTrigger(trigger);
builder.SetTaskEntryPointClsid(entryPointClsid);
BackgroundTaskRegistration registration;
if (builder.Validate())
{
registration = builder.Register(taskName);
}
else
{
registration = null;
}
return registration;
}
RegisterBackgroundTaskWithSystem(new TimeTrigger(15, false), typeof(TimeTriggeredTask).GUID, typeof(TimeTriggeredTask).Name);
O RegisterBackgroundTaskWithSystem método assume três parâmetros:
-
trigger: O gatilho que iniciará a tarefa em segundo plano. -
entryPointClsid: O ID da classe do ponto de entrada da tarefa em segundo plano. -
taskName: O nome da tarefa em segundo plano.
O método RegisterBackgroundTaskWithSystem cria uma nova instância da classe BackgroundTaskBuilder e define o disparador e o ID da classe do ponto de entrada para a tarefa em segundo plano. O método regista então a tarefa em segundo plano junto do sistema.
Observação
Esta classe não é ágil, o que significa que precisa de considerar o seu modelo de encadeamento e comportamento de serialização. Para obter mais informações, consulte Threading and Marshaling (C++/CX) e Using Windows Runtime objects in a multithreaded environment (.NET).
Lidar com o standby moderno numa tarefa em segundo plano
O BackgroundTaskBuilder e APIs relacionadas já permitem que aplicações de ambiente de trabalho empacotadas executem tarefas em segundo plano. A API agora expande estas APIs para permitir que estas aplicações executem código em modo de espera moderno. A atualização também adiciona propriedades que podem ser consultadas por uma aplicação para determinar se o sistema irá reduzir as tarefas em segundo plano da aplicação enquanto estiver no modo de espera moderno, de modo a poupar a bateria. Isto permite cenários como aplicações receberem chamadas VoIP ou outras notificações push a partir do modo de espera moderno.
Observação
"Aplicações de ambiente de trabalho empacotadas" nesta secção refere-se a aplicações Win32 que têm identidade de pacote (ou seja, são aplicações Desktop Bridge ou Sparse Signed Packaged) e que têm uma função principal (ou wmain) como ponto de entrada.
O exemplo seguinte mostra como um programador de aplicações pode usar a API BackgroundTaskBuilder para registar, no máximo, uma tarefa com o nome especificado. O exemplo também mostra como verificar e ativar o registo da tarefa para executar em modo de espera moderno para as tarefas críticas da aplicação.
// The following namespace is required for BackgroundTaskBuilder APIs.
using Windows.ApplicationModel.Background;
// The following namespace is required for API version checks.
using Windows.Foundation.Metadata;
// The following namespace is used for showing Toast Notifications. This
// namespace requires the Microsoft.Toolkit.Uwp.Notifications NuGet package
// version 7.0 or greater.
using Microsoft.Toolkit.Uwp.Notifications;
// Incoming calls are considered to be critical tasks to the operation of the app.
const string IncomingCallTaskName = "IncomingCallTask";
const string NotificationTaskName = "NotificationTask";
const string PrefetchTaskName = "PrefetchTask";
public static bool IsAllowedInBackground(BackgroundAccessStatus status) {
return ((status != BackgroundAccessStatus.Denied) &&
(status != BackgroundAccessStatus.DeniedBySystemPolicy) &&
(status != BackgroundAccessStatus.DeniedByUser) &&
(status != BackgroundAccessStatus.Unspecified));
}
public async void RegisterTask(IBackgroundTrigger trigger,
Guid entryPointClsid,
string taskName,
bool isRunInStandbyRequested)
{
var taskBuilder = new BackgroundTaskBuilder();
taskBuilder.SetTrigger(trigger);
taskBuilder.SetTaskEntryPointClsid(entryPointClsid);
// Only the most critical background work should be allowed to proceed in
// modern standby. Additionally, some platforms may not support modern
// or running background tasks in modern standby at all. Only attempt to
// request modern standby execution if both are true. Requesting network
// is necessary when running in modern standby to handle push notifications.
if (IsRunInStandbyRequested && taskBuilder.IsRunningTaskInStandbySupported)
{
var accessStatus = BackgroundExecutionManager.GetAccessStatusForModernStandby();
if (!IsAllowedInBackground(accessStatus)
{
await BackgroundExecutionManager.RequestAccessKindForModernStandby(
BackgroundAccessRequestKind.AllowedSubjectToSystemPolicy,
"This app wants to receive incoming notifications while your device is asleep");
}
accessStatus = BackgroundExecutionManager.GetAccessStatusForModernStandby();
if (IsAllowedInBackground(accessStatus)
{
taskBuilder.IsRunningTaskInStandbyRequested = true;
taskBuilder.IsNetworkRequested = true;
}
}
// Check that the registration is valid before attempting to register.
if (taskBuilder.IsRegistrationValid)
{
// If a task with the specified name already exists, it is unregistered
// before a new one is registered. Note this API may still fail from
// catastrophic failure (e.g., memory allocation failure).
taskBuilder.Register(taskName);
}
return;
}
RegisterTask(new PushNotificationTrigger(), "{INSERT-YOUR-GUID-HERE}", IncomingCallTaskName, true);
Verifique se as tarefas em segundo plano excederam o orçamento no modo de espera moderno
O seguinte código de exemplo mostra como um programador de aplicações pode usar o BackgroundWorkCost.WasApplicationThrottledInStandby e o BackgroundWorkCost.ApplicationEnergyUseLevel para monitorizar e reagir ao facto de as suas tarefas em segundo plano esgotarem o orçamento da aplicação. O programador da aplicação pode reagir ao reduzir a execução de tarefas de menor prioridade durante o modo standby moderno. Note que isto depende do código do exemplo anterior.
public async void ReduceBackgroundCost()
{
BackgroundTaskRegistration callTask;
BackgroundTaskRegistration notificationTask;
BackgroundTaskRegistration prefetchTask;
// Nothing to do if the app was not or will not be throttled.
if (!BackgroundWorkCost.WasApplicationThrottledInStandby &&
(BackgroundWorkCost.ApplicationEnergyUseLevel != StandbyEnergyUseLevel.OverBudget))
{
return;
}
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
switch (task.Value.Name) {
case IncomingCallTaskName:
callTask = task.Value;
break;
case NotificationTaskName:
notificationTask = task.Value;
break;
case PrefetchTaskName:
prefetchTask = task.Value;
break;
default:
}
}
if (callTask.WasTaskThrottledInStandby)
{
// Unset the throttle flag after acknowledging it so the app can
// react to the same task being throttled again in the future.
task.Value.WasTaskThrottledInStandby = false;
// Notify the user that the notification was missed.
new ToastContentBuilder()
.AddText("You missed a call")
.AddText(task.Value.Name)
.Show();
// Because the incoming calls were not activated, demote less notifications
// tasks so the calls can be delivered promptly in the future.
RegisterTask(notificationTask.Value.Trigger,
typeof(TimeTriggeredTask).GUID,
notificationTask.Value.Name,
false);
}
// Note that if incoming call tasks were throttled in some previous modern
// standby session, the application energy use was over budget for some period.
// Demote unimportant tasks like prefetch work to avoid calls and notifications
// from being throttled.
if (callTask.WasTaskThrottledInStandby) ||
(BackgroundWorkCost.ApplicationEnergyUseLevel == StandbyEnergyUseLevel.OverBudget))
{
RegisterTask(prefetchTask.Value.Trigger,
typeof(TimeTriggeredTask).GUID,
prefetchTask.Value.Name,
false);
}
return;
}
Monitorizar as tendências de utilização de energia de tarefas em segundo plano
A seguir, é apresentada uma atualização incremental de ponta a ponta para o código de exemplo em C++WinRT/C# no GitHub.
O exemplo mostra como pode usar o BackgroundWorkCost.ApplicationEnergyUseTrend para monitorizar como as suas tarefas em segundo plano tendem a esgotar o seu orçamento. Pode, igualmente, parar as tarefas em segundo plano mais dispendiosas de correrem em modo standby moderno e evitar que continuem se a aplicação estiver a consumir o limite de recursos demasiado rapidamente. Este exemplo baseia-se em código de exemplos anteriores.
public async void ReduceBackgroundCostPreemptively()
{
BackgroundTaskRegistration mostExpensiveTask = null;
// We can't do anything preemptively since the trend isn't known.
if (!BackgroundWorkCost.IsApplicationEnergyUseTrendKnown)
{
return;
}
// The app is not trending towards being over budget, so this method can
// return early.
if ((BackgroundWorkCost.ApplicationEnergyUseTrend != EnergyUseTrend.OverBudget) &&
(BackgroundWorkCost.ApplicationEnergyUseTrend != EnergyUseTrend.OverHalf))
{
return;
}
// The application is going exceeding its budget very quickly. Demote the
// most expensive task that is not the call task before call tasks start being
// throttled.
if (BackgroundWorkCost.ApplicationEnergyUseTrend == EnergyUseTrend.OverBudget)
{
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
if ((task.Value.Name != IncomingCallTaskName) &&
((mostExpensiveTask == null) ||
(mostExpensiveTask.ApplicationEnergyUseTrendContributionPercentage <
task.Value.ApplicationEnergyUseTrendContributionPercentage)))
{
mostExpensiveTask = task.Value;
}
}
}
if (mostExpensiveTask != null)
{
RegisterTask(mostExpensiveTask.Trigger,
typeof(TimeTriggeredTask).GUID,
mostExpensiveTask.Name,
false);
}
// The application is trending toward eventually exceeding its budget. Demote the
// least important prefetch task before calls and notifications are throttled.
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
if (task.Value.Name == PrefetchTaskName) {
RegisterTask(task.Value.Trigger,
typeof(TimeTriggeredTask).GUID,
task.Value.Name,
false);
}
}
return;
}
Tarefas em segundo plano e conectividade de rede
Se a sua tarefa em segundo plano exigir ligação à rede, esteja ciente das seguintes considerações.
Gatilhos relacionados com a rede
- Use um SocketActivityTrigger para ativar a tarefa em segundo plano quando um pacote for recebido e precisar de realizar uma tarefa de curta duração. Após a realização da tarefa, a tarefa em segundo plano deve terminar para poupar energia.
- Use um ControlChannelTrigger para ativar a tarefa em segundo plano quando um pacote for recebido e precisar de realizar uma tarefa de longa duração.
Condições e indicadores relacionados com a rede
- Adicione a condição InternetAvailable (BackgroundTaskBuilder.AddCondition) à sua tarefa em segundo plano para atrasar o disparo da tarefa em segundo plano até que a pilha de rede esteja a funcionar. Esta condição poupa energia porque a tarefa em segundo plano não será executada até que o acesso à rede esteja disponível. Esta condição não proporciona ativação em tempo real.
- Independentemente do gatilho que usar, defina o IsNetworkRequested na tarefa em segundo plano para garantir que a rede permanece ativa enquanto a tarefa em segundo plano está a correr. Isto indica à infraestrutura de tarefas em segundo plano para manter a rede ativa enquanto a tarefa está a ser executada, mesmo que o dispositivo tenha entrado em modo de Espera Conectado. Se a sua tarefa em segundo plano não usar o IsNetworkRequested, então a tarefa em segundo plano não conseguirá aceder à rede quando estiver em modo Connected Standby.
Conteúdo relacionado
Windows developer