Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Erfahren Sie, wie Sie eine Hintergrundaufgabe in Ihrer App mit der Windows-Runtime (WinRT) BackgroundTaskBuilder Klasse erstellen und registrieren.
Registrieren einer Hintergrundaufgabe
Ein vollständiges Beispiel für die Registrierung einer Hintergrundaufgabe in einer UWP-App (Universelle Windows-Plattform) finden Sie im BackgroundTask-Beispiel.
Das folgende Beispiel zeigt die Registrierung einer Win32-COM-Aufgabe, die auf einem wiederkehrenden 15-Minuten-Timer ausgeführt wird.
Um eine Hintergrundaufgabe zu registrieren, müssen Sie zunächst eine neue Instanz der BackgroundTaskBuilder Klasse erstellen. Die BackgroundTaskBuilder Klasse wird verwendet, um Hintergrundaufgaben in Ihrer App zu erstellen und zu registrieren. Im folgenden Codebeispiel wird veranschaulicht, wie eine neue Instanz der BackgroundTaskBuilder Klasse erstellt wird:
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);
Die RegisterBackgroundTaskWithSystem-Methode akzeptiert drei Parameter:
-
trigger: Der Trigger, der die Hintergrundaufgabe startet. -
entryPointClsid: Die Klassen-ID des Einstiegspunkts der Hintergrundaufgabe. -
taskName: Der Name der Hintergrundaufgabe.
Die RegisterBackgroundTaskWithSystem-Methode erstellt eine neue Instanz der BackgroundTaskBuilder Klasse und legt die Trigger- und Einstiegspunktklassen-ID für die Hintergrundaufgabe fest. Die Methode registriert dann die Hintergrundaufgabe beim System.
Anmerkung
Diese Klasse ist nicht agil, was bedeutet, dass Sie das Threadingmodell und das Marshallingverhalten berücksichtigen müssen. Weitere Informationen finden Sie unter Threading und Marshaling (C++/CX) und Verwenden von Windows-Runtime-Objekten in einer Multithreadumgebung (.NET).
Behandlung des modernen Standbymodus in einer Hintergrundaufgabe
Die BackgroundTaskBuilder und zugehörige APIs ermöglichen bereits das Ausführen von Hintergrundaufgaben. Die API erweitert nun diese APIs, damit diese Appls Code im modernen Standbymodus ausführen können. Das Update fügt außerdem Eigenschaften hinzu, die von einer App abgefragt werden können, um festzustellen, ob das System Hintergrundaufgaben für die Anwendung im modernen Standbymodus drosselt, um die Akkulaufzeit zu sparen. Dies ermöglicht Szenarien wie Apps, die VoIP-Anrufe empfangen, oder andere Pushbenachrichtigungen aus dem modernen Standbymodus.
Anmerkung
"Verpackte Desktopanwendungen" in diesem Abschnitt beziehen sich auf Win32-Anwendungen mit Paketidentität (d. h. Desktop Bridge oder Sparse Signed Packaged-Anwendungen) und die eine Hauptfunktion (oder wmain) als Einstiegspunkt haben.
Das folgende Beispiel zeigt, wie ein App-Entwickler die BackgroundTaskBuilder-API verwenden kann, um höchstens eine Aufgabe mit dem angegebenen Aufgabennamen zu registrieren. Das Beispiel zeigt auch, wie Sie die Aufgabenregistrierung überprüfen und optieren können, damit sie im modernen Standbymodus für die wichtigsten Aufgaben der Anwendung ausgeführt wird.
// 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);
Überprüfen, ob Hintergrundaufgaben ihr Budget im modernen Standbymodus überschritten haben
Im folgenden Beispielcode wird gezeigt, wie ein App-Entwickler die BackgroundWorkCost.WasApplicationThrottledInStandby und BackgroundWorkCost.ApplicationEnergyUseLevel verwenden kann, um zu überwachen und darauf zu reagieren, wenn ihre Hintergrundaufgaben das App-Budget aufgebraucht haben. Der App-Entwickler reagiert möglicherweise, indem die Arbeit mit niedrigerer Priorität im modernen Standbymodus reduziert wird. Beachten Sie, dass der Code aus dem vorherigen Beispiel verwendet wird.
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;
}
Überwachen von Trends für die Energienutzung von Hintergrundaufgaben
Es folgt ein inkrementelles End-to-End-Update des untenstehenden C++WinRT/C#-Beispielcodes auf GitHub.
Das Beispiel zeigt, wie Sie den BackgroundWorkCost.ApplicationEnergyUseTrend verwenden können, um zu überwachen, wie Ihre Hintergrundaufgaben dazu tendieren, ihr Budget auszuschöpfen. Sie können auch verhindern, dass die teuersten Hintergrundaufgaben im modernen Standbymodus ausgeführt werden und verhindern, dass Hintergrundaufgaben im modernen Standbymodus ausgeführt werden, wenn ihre App ihr Budget zu schnell verwendet. Dieses Beispiel basiert auf Code aus vorherigen Beispielen.
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;
}
Hintergrundaufgaben und Netzwerkkonnektivität
Wenn Ihre Hintergrundaufgabe netzwerkkonnektivität erfordert, beachten Sie die folgenden Überlegungen.
Netzwerkbezogene Trigger
- Verwenden Sie einen SocketActivityTrigger-, um die Hintergrundaufgabe zu aktivieren, wenn ein Paket empfangen wird und Sie eine kurzlebige Aufgabe ausführen müssen. Nach dem Ausführen der Aufgabe sollte die Hintergrundaufgabe beendet werden, um Energie zu sparen.
- Verwenden Sie einen ControlChannelTrigger, um die Hintergrundaufgabe zu aktivieren, wenn ein Paket empfangen wird und wenn Sie eine langlebige Aufgabe ausführen müssen.
Netzwerkbezogene Bedingungen und Kennzeichnungen
- Fügen Sie die Bedingung "InternetAvailable" (BackgroundTaskBuilder.AddCondition) zu Ihrer Hintergrundaufgabe hinzu, um das Auslösen der Hintergrundaufgabe zu verzögern, bis der Netzwerkstapel ausgeführt wird. Diese Bedingung spart Energie, da die Hintergrundaufgabe erst ausgeführt wird, wenn der Netzwerkzugriff verfügbar ist. Diese Bedingung bietet keine Echtzeitaktivierung.
- Unabhängig davon, welchen Trigger Sie verwenden, setzen Sie IsNetworkRequested für Ihre Hintergrundaufgabe fest, um sicherzustellen, dass das Netzwerk während der Ausführung der Hintergrundaufgabe aktiv bleibt. Dadurch wird der Hintergrundaufgabeninfrastruktur mitgeteilt, das Netzwerk während der Ausführung der Aufgabe beizubehalten, auch wenn das Gerät in den Modus "Verbundener Standbymodus" gewechselt ist. Wenn Ihre Hintergrundaufgabe IsNetworkRequestednicht verwendet, dann kann die Hintergrundaufgabe im verbundenen Standbymodus nicht auf das Netzwerk zugreifen.
Verwandte Inhalte
Windows developer