Créer et inscrire une tâche en arrière-plan hors processus
API importantes
Créez une classe de tâche en arrière-plan et inscrivez-la pour s’exécuter lorsque votre application n’est pas au premier plan. Cette rubrique montre comment créer et inscrire une tâche en arrière-plan qui s’exécute dans un processus distinct du processus de votre application. Pour effectuer un travail en arrière-plan directement dans l’application de premier plan, consultez Créer et inscrire une tâche en arrière-plan in-process.
Remarque
Si vous utilisez une tâche en arrière-plan pour lire des médias en arrière-plan, consultez Lire le média en arrière-plan pour plus d’informations sur les améliorations apportées à Windows 10, version 1607, ce qui facilite grandement la lecture.
Remarque
Si vous implémentez une tâche en arrière-plan hors processus dans une application de bureau C# avec .NET 6 ou version ultérieure, utilisez la prise en charge de création C#/WinRT pour créer un composant Windows Runtime. Cela s’applique aux applications utilisant le Kit de développement logiciel (SDK) d’application Windows, WinUI 3, WPF ou WinForms. Consultez l’exemple de tâche en arrière-plan pour obtenir un exemple.
Créer la classe Task en arrière-plan
Vous pouvez exécuter du code en arrière-plan en écrivant des classes qui implémentent l’interface IBackgroundTask . Ce code s’exécute lorsqu’un événement spécifique est déclenché à l’aide, par exemple, de SystemTrigger ou maintenanceTrigger.
Les étapes suivantes vous montrent comment écrire une nouvelle classe qui implémente l’interface IBackgroundTask .
- Créez un projet pour les tâches en arrière-plan et ajoutez-le à votre solution. Pour ce faire, cliquez avec le bouton droit sur votre nœud de solution dans le Explorateur de solutions, puis sélectionnez Ajouter>un nouveau projet. Sélectionnez ensuite le type de projet composant Windows Runtime, nommez le projet, puis cliquez sur OK.
- Référencez le projet de tâches en arrière-plan à partir de votre projet d’application plateforme Windows universelle (UWP). Pour une application C# ou C++, dans votre projet d’application, cliquez avec le bouton droit sur Références et sélectionnez Ajouter une nouvelle référence. Sous Solution, sélectionnez Projets , puis sélectionnez le nom de votre projet de tâche en arrière-plan, puis cliquez sur Ok.
- Dans le projet de tâches en arrière-plan, ajoutez une nouvelle classe qui implémente l’interface IBackgroundTask . La méthode IBackgroundTask.Run est un point d’entrée obligatoire qui sera appelé lorsque l’événement spécifié est déclenché ; cette méthode est requise dans chaque tâche en arrière-plan.
Remarque
La classe de tâche en arrière-plan elle-même, et toutes les autres classes du projet de tâche en arrière-plan, doivent être des classes publiques qui sont scellées (ou finales).
L’exemple de code suivant montre un point de départ très simple pour une classe de tâches en arrière-plan.
// ExampleBackgroundTask.cs
using Windows.ApplicationModel.Background;
namespace Tasks
{
public sealed class ExampleBackgroundTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
}
}
}
// First, add ExampleBackgroundTask.idl, and then build.
// ExampleBackgroundTask.idl
namespace Tasks
{
[default_interface]
runtimeclass ExampleBackgroundTask : Windows.ApplicationModel.Background.IBackgroundTask
{
ExampleBackgroundTask();
}
}
// ExampleBackgroundTask.h
#pragma once
#include "ExampleBackgroundTask.g.h"
namespace winrt::Tasks::implementation
{
struct ExampleBackgroundTask : ExampleBackgroundTaskT<ExampleBackgroundTask>
{
ExampleBackgroundTask() = default;
void Run(Windows::ApplicationModel::Background::IBackgroundTaskInstance const& taskInstance);
};
}
namespace winrt::Tasks::factory_implementation
{
struct ExampleBackgroundTask : ExampleBackgroundTaskT<ExampleBackgroundTask, implementation::ExampleBackgroundTask>
{
};
}
// ExampleBackgroundTask.cpp
#include "pch.h"
#include "ExampleBackgroundTask.h"
namespace winrt::Tasks::implementation
{
void ExampleBackgroundTask::Run(Windows::ApplicationModel::Background::IBackgroundTaskInstance const& taskInstance)
{
throw hresult_not_implemented();
}
}
// ExampleBackgroundTask.h
#pragma once
using namespace Windows::ApplicationModel::Background;
namespace Tasks
{
public ref class ExampleBackgroundTask sealed : public IBackgroundTask
{
public:
ExampleBackgroundTask();
virtual void Run(IBackgroundTaskInstance^ taskInstance);
void OnCompleted(
BackgroundTaskRegistration^ task,
BackgroundTaskCompletedEventArgs^ args
);
};
}
// ExampleBackgroundTask.cpp
#include "ExampleBackgroundTask.h"
using namespace Tasks;
void ExampleBackgroundTask::Run(IBackgroundTaskInstance^ taskInstance)
{
}
- Si vous exécutez du code asynchrone dans votre tâche en arrière-plan, votre tâche en arrière-plan doit utiliser un report. Si vous n’utilisez pas de report, le processus de tâche en arrière-plan peut se terminer de manière inattendue si la méthode Run retourne avant que tout travail asynchrone ne s’exécute à la fin.
Demandez le report dans la méthode Run avant d’appeler la méthode asynchrone. Enregistrez le report dans un membre de données de classe afin qu’il soit accessible à partir de la méthode asynchrone. Déclarez le report terminé une fois le code asynchrone terminé.
L’exemple de code suivant obtient le report, l’enregistre et le libère une fois le code asynchrone terminé.
BackgroundTaskDeferral _deferral; // Note: defined at class scope so that we can mark it complete inside the OnCancel() callback if we choose to support cancellation
public async void Run(IBackgroundTaskInstance taskInstance)
{
_deferral = taskInstance.GetDeferral();
//
// TODO: Insert code to start one or more asynchronous methods using the
// await keyword, for example:
//
// await ExampleMethodAsync();
//
_deferral.Complete();
}
// ExampleBackgroundTask.h
...
private:
Windows::ApplicationModel::Background::BackgroundTaskDeferral m_deferral{ nullptr };
// ExampleBackgroundTask.cpp
...
Windows::Foundation::IAsyncAction ExampleBackgroundTask::Run(
Windows::ApplicationModel::Background::IBackgroundTaskInstance const& taskInstance)
{
m_deferral = taskInstance.GetDeferral(); // Note: defined at class scope so that we can mark it complete inside the OnCancel() callback if we choose to support cancellation.
// TODO: Modify the following line of code to call a real async function.
co_await ExampleCoroutineAsync(); // Run returns at this point, and resumes when ExampleCoroutineAsync completes.
m_deferral.Complete();
}
void ExampleBackgroundTask::Run(IBackgroundTaskInstance^ taskInstance)
{
m_deferral = taskInstance->GetDeferral(); // Note: defined at class scope so that we can mark it complete inside the OnCancel() callback if we choose to support cancellation.
//
// TODO: Modify the following line of code to call a real async function.
// Note that the task<void> return type applies only to async
// actions. If you need to call an async operation instead, replace
// task<void> with the correct return type.
//
task<void> myTask(ExampleFunctionAsync());
myTask.then([=]() {
m_deferral->Complete();
});
}
Remarque
En C#, les méthodes asynchrones de votre tâche en arrière-plan peuvent être appelées à l’aide des mots clés asynchrones/await . En C++/CX, un résultat similaire peut être obtenu à l’aide d’une chaîne de tâches.
Pour plus d’informations sur les modèles asynchrones, consultez Programmation asynchrone. Pour obtenir des exemples supplémentaires d’utilisation des reports pour empêcher l’arrêt précoce d’une tâche en arrière-plan, consultez l’exemple de tâche en arrière-plan.
Les étapes suivantes sont effectuées dans l’une de vos classes d’application (par exemple, MainPage.xaml.cs).
Remarque
Vous pouvez également créer une fonction dédiée à l’inscription de tâches en arrière-plan : consultez Inscrire une tâche en arrière-plan. Dans ce cas, au lieu d’utiliser les trois étapes suivantes, vous pouvez simplement construire le déclencheur et le fournir à la fonction d’inscription avec le nom de la tâche, le point d’entrée de tâche et (éventuellement) une condition.
Inscrire la tâche en arrière-plan à exécuter
- Déterminez si la tâche en arrière-plan est déjà inscrite en itérant via la propriété BackgroundTaskRegistration.AllTasks. Cette étape est importante ; si votre application ne vérifie pas les inscriptions de tâches en arrière-plan existantes, elle peut facilement inscrire la tâche plusieurs fois, ce qui provoque des problèmes de performances et la durée maximale du processeur disponible de la tâche avant que le travail ne puisse se terminer.
L’exemple suivant itère sur la propriété AllTasks et définit une variable d’indicateur sur true si la tâche est déjà inscrite.
var taskRegistered = false;
var exampleTaskName = "ExampleBackgroundTask";
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
if (task.Value.Name == exampleTaskName)
{
taskRegistered = true;
break;
}
}
std::wstring exampleTaskName{ L"ExampleBackgroundTask" };
auto allTasks{ Windows::ApplicationModel::Background::BackgroundTaskRegistration::AllTasks() };
bool taskRegistered{ false };
for (auto const& task : allTasks)
{
if (task.Value().Name() == exampleTaskName)
{
taskRegistered = true;
break;
}
}
// The code in the next step goes here.
boolean taskRegistered = false;
Platform::String^ exampleTaskName = "ExampleBackgroundTask";
auto iter = BackgroundTaskRegistration::AllTasks->First();
auto hascur = iter->HasCurrent;
while (hascur)
{
auto cur = iter->Current->Value;
if(cur->Name == exampleTaskName)
{
taskRegistered = true;
break;
}
hascur = iter->MoveNext();
}
- Si la tâche en arrière-plan n’est pas déjà inscrite, utilisez BackgroundTaskBuilder pour créer une instance de votre tâche en arrière-plan. Le point d’entrée de tâche doit être le nom de votre classe de tâche en arrière-plan précédée de l’espace de noms.
Le déclencheur de tâche en arrière-plan contrôle l’exécution de la tâche en arrière-plan. Pour obtenir la liste des déclencheurs possibles, consultez SystemTrigger.
Par exemple, ce code crée une tâche en arrière-plan et la définit pour s’exécuter lorsque le déclencheur TimeZoneChanged se produit :
var builder = new BackgroundTaskBuilder();
builder.Name = exampleTaskName;
builder.TaskEntryPoint = "Tasks.ExampleBackgroundTask";
builder.SetTrigger(new SystemTrigger(SystemTriggerType.TimeZoneChange, false));
if (!taskRegistered)
{
Windows::ApplicationModel::Background::BackgroundTaskBuilder builder;
builder.Name(exampleTaskName);
builder.TaskEntryPoint(L"Tasks.ExampleBackgroundTask");
builder.SetTrigger(Windows::ApplicationModel::Background::SystemTrigger{
Windows::ApplicationModel::Background::SystemTriggerType::TimeZoneChange, false });
// The code in the next step goes here.
}
auto builder = ref new BackgroundTaskBuilder();
builder->Name = exampleTaskName;
builder->TaskEntryPoint = "Tasks.ExampleBackgroundTask";
builder->SetTrigger(ref new SystemTrigger(SystemTriggerType::TimeZoneChange, false));
- Vous pouvez ajouter une condition pour contrôler quand votre tâche s’exécutera après l’événement de déclencheur (facultatif). Par exemple, si vous ne souhaitez pas que la tâche s’exécute tant que l’utilisateur n’est pas présent, utilisez la condition UserPresent. Pour obtenir la liste des conditions possibles, consultez SystemConditionType.
L’exemple de code suivant affecte une condition exigeant que l’utilisateur soit présent :
builder.AddCondition(new SystemCondition(SystemConditionType.UserPresent));
builder.AddCondition(Windows::ApplicationModel::Background::SystemCondition{ Windows::ApplicationModel::Background::SystemConditionType::UserPresent });
// The code in the next step goes here.
builder->AddCondition(ref new SystemCondition(SystemConditionType::UserPresent));
- Inscrivez la tâche en arrière-plan en appelant la méthode Register sur l’objet BackgroundTaskBuilder . Stockez le résultat BackgroundTaskRegistration afin qu’il puisse être utilisé à l’étape suivante.
Le code suivant inscrit la tâche en arrière-plan et stocke le résultat :
BackgroundTaskRegistration task = builder.Register();
Windows::ApplicationModel::Background::BackgroundTaskRegistration task{ builder.Register() };
BackgroundTaskRegistration^ task = builder->Register();
Remarque
Les applications Windows universelles doivent appeler RequestAccessAsync avant d’inscrire l’un des types de déclencheurs en arrière-plan.
Pour vous assurer que votre application Windows universelle continue de s’exécuter correctement après avoir publié une mise à jour, utilisez le déclencheur ServicingComplete (voir SystemTriggerType) pour effectuer toutes les modifications de configuration postérieures à la mise à jour, telles que la migration de la base de données de l’application et l’inscription de tâches en arrière-plan. Il est recommandé de désinscrire les tâches en arrière-plan associées à la version précédente de l’application (voir RemoveAccess) et d’inscrire des tâches en arrière-plan pour la nouvelle version de l’application (voir RequestAccessAsync) pour l’instant.
Pour plus d’informations, consultez Instructions pour les tâches en arrière-plan.
Gérer l’achèvement des tâches en arrière-plan à l’aide de gestionnaires d’événements
Vous devez inscrire une méthode auprès de BackgroundTaskCompletedEventHandler, afin que votre application puisse obtenir des résultats à partir de la tâche en arrière-plan. Lorsque l’application est lancée ou reprise, la méthode marquée est appelée si la tâche en arrière-plan s’est terminée depuis la dernière fois que l’application était au premier plan. (La méthode OnCompleted est appelée immédiatement si la tâche en arrière-plan se termine pendant que votre application est au premier plan.)
- Écrivez une méthode OnCompleted pour gérer l’achèvement des tâches en arrière-plan. Par exemple, le résultat de la tâche en arrière-plan peut entraîner une mise à jour de l’interface utilisateur. L’empreinte de méthode indiquée ici est requise pour la méthode de gestionnaire d’événements OnCompleted, même si cet exemple n’utilise pas le paramètre d’arguments .
L’exemple de code suivant reconnaît la saisie semi-automatique des tâches en arrière-plan et appelle un exemple de méthode de mise à jour de l’interface utilisateur qui prend une chaîne de message.
private void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args)
{
var settings = Windows.Storage.ApplicationData.Current.LocalSettings;
var key = task.TaskId.ToString();
var message = settings.Values[key].ToString();
UpdateUI(message);
}
void UpdateUI(winrt::hstring const& message)
{
MyTextBlock().Dispatcher().RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, [=]()
{
MyTextBlock().Text(message);
});
}
void OnCompleted(
Windows::ApplicationModel::Background::BackgroundTaskRegistration const& sender,
Windows::ApplicationModel::Background::BackgroundTaskCompletedEventArgs const& /* args */)
{
// You'll previously have inserted this key into local settings.
auto settings{ Windows::Storage::ApplicationData::Current().LocalSettings().Values() };
auto key{ winrt::to_hstring(sender.TaskId()) };
auto message{ winrt::unbox_value<winrt::hstring>(settings.Lookup(key)) };
UpdateUI(message);
}
void MainPage::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args)
{
auto settings = ApplicationData::Current->LocalSettings->Values;
auto key = task->TaskId.ToString();
auto message = dynamic_cast<String^>(settings->Lookup(key));
UpdateUI(message);
}
Remarque
Les mises à jour de l’interface utilisateur doivent être effectuées de manière asynchrone pour éviter de conserver le thread d’interface utilisateur. Pour obtenir un exemple, consultez la méthode UpdateUI dans l’exemple de tâche en arrière-plan.
- Revenez à l’emplacement où vous avez inscrit la tâche en arrière-plan. Après cette ligne de code, ajoutez un nouvel objet BackgroundTaskCompletedEventHandler. Fournissez votre méthode OnCompleted comme paramètre pour le constructeur BackgroundTaskCompletedEventHandler .
L’exemple de code suivant ajoute un BackgroundTaskCompletedEventHandler à BackgroundTaskRegistration :
task.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);
task.Completed({ this, &MainPage::OnCompleted });
task->Completed += ref new BackgroundTaskCompletedEventHandler(this, &MainPage::OnCompleted);
Déclarez dans le manifeste de l’application que votre application utilise des tâches en arrière-plan
Pour que votre application puisse exécuter des tâches en arrière-plan, vous devez déclarer chaque tâche en arrière-plan dans le manifeste de l’application. Si votre application tente d’inscrire une tâche en arrière-plan avec un déclencheur qui n’est pas répertorié dans le manifeste, l’inscription de la tâche en arrière-plan échoue avec une erreur « classe runtime non inscrite ».
- Ouvrez le concepteur de manifeste de package en ouvrant le fichier nommé Package.appxmanifest.
- Ouvrez l’onglet Déclarations .
- Dans la liste déroulante Déclarations disponibles, sélectionnez Tâches en arrière-plan, puis cliquez sur Ajouter.
- Cochez la case événement système.
- Dans le point d’entrée : zone de texte, entrez l’espace de noms et le nom de votre classe d’arrière-plan, qui est pour cet exemple, Tasks.ExampleBackgroundTask.
- Fermez le concepteur de manifeste.
L’élément Extensions suivant est ajouté à votre fichier Package.appxmanifest pour inscrire la tâche en arrière-plan :
<Extensions>
<Extension Category="windows.backgroundTasks" EntryPoint="Tasks.ExampleBackgroundTask">
<BackgroundTasks>
<Task Type="systemEvent" />
</BackgroundTasks>
</Extension>
</Extensions>
Résumé et étapes suivantes
Vous devez maintenant comprendre les principes de base de l’écriture d’une classe de tâches en arrière-plan, l’inscription de la tâche en arrière-plan à partir de votre application et la reconnaissance de votre application lorsque la tâche en arrière-plan est terminée. Vous devez également comprendre comment mettre à jour le manifeste de l’application afin que votre application puisse inscrire correctement la tâche en arrière-plan.
Remarque
Téléchargez l’exemple de tâche en arrière-plan pour voir des exemples de code similaires dans le contexte d’une application UWP complète et robuste qui utilise des tâches en arrière-plan.
Consultez les rubriques connexes suivantes pour obtenir des informations de référence sur l’API, des instructions conceptuelles sur les tâches en arrière-plan et des instructions plus détaillées sur l’écriture d’applications qui utilisent des tâches en arrière-plan.
Rubriques connexes
Rubriques d’instructions détaillées sur les tâches en arrière-plan
- Répondre aux événements système avec des tâches en arrière-plan
- Inscrire une tâche en arrière-plan
- Définir des conditions pour l’exécution d’une tâche en arrière-plan
- Utiliser un déclencheur de maintenance
- Gérer une tâche en arrière-plan annulée
- Surveiller la progression et l’achèvement des tâches en arrière-plan
- Exécuter une tâche en arrière-plan en fonction d’un minuteur
- Créez et inscrivez une tâche en arrière-plan in-process.
- Convertir une tâche en arrière-plan hors processus en une tâche en arrière-plan in-process
Conseils sur les tâches en arrière-plan
- Recommandations relatives aux tâches en arrière-plan
- Déboguer une tâche en arrière-plan
- Comment déclencher des événements d’interruption, de reprise et d’arrière-plan dans des applications UWP (lors du débogage)
Informations de référence sur l’API de tâche en arrière-plan