Регистрация фоновой задачиRegister a background task

Важные APIImportant APIs

Сведения о создании функции, которую можно многократно использовать для безопасной регистрации большинства фоновых задач.Learn how to create a function that can be re-used to safely register most background tasks.

Эта статья относится как к внутрипроцессным, так и к внепроцессным фоновым задачам.This topic is applicable to both in-process background tasks and out-of-process background tasks. В этой статье предполагается, что у вас уже есть фоновая задача, которую нужно зарегистрировать.This topic assumes that you already have a background task that needs to be registered. (О том, как написать фоновую задачу, см. в статье Создание и регистрация внепроцессной фоновой задачи или Создание и регистрация внутрипроцессной фоновой задачи).(See Create and register a background task that runs out-of-process or Create and register an in-process background task for information about how to write a background task).

Этот раздел содержит краткий обзор служебной функции, которая регистрирует фоновые задачи.This topic walks through a utility function that registers background tasks. Прежде чем несколько раз зарегистрировать задачу, эта служебная функция проверяет наличие существующих регистраций, чтобы избежать проблем, связанных с многократными регистрациями. Она может также применять условие системы к фоновой задаче.This utility function checks for existing registrations first before registering the task multiple times to avoid problems with multiple registrations, and it can apply a system condition to the background task. Этот обзор включает полный рабочий пример данной служебной функции.The walkthrough includes a complete, working example of this utility function.

Примечание.Note  

Универсальные приложения для Windows должны вызвать RequestAccessAsync перед регистрацией любых типов фоновых триггеров.Universal Windows apps must call RequestAccessAsync before registering any of the background trigger types.

Чтобы универсальное приложение для Windows продолжало правильно работать после выпуска обновления, необходимо вызвать метод RemoveAccess, а затем — метод RequestAccessAsync при запуске приложения после обновления.To ensure that your Universal Windows app continues to run properly after you release an update, you must call RemoveAccess and then call RequestAccessAsync when your app launches after being updated. Дополнительные сведения см. в разделе Руководство по фоновым задачам.For more information, see Guidelines for background tasks.

Определение подписи и типа возвращаемых данных методаDefine the method signature and return type

Этот метод принимает точку входа задачи, имя задачи, предварительно построенный триггер фоновой задачи и (необязательно) условие SystemCondition для фоновой задачи.This method takes in the task entry point, task name, a pre-constructed background task trigger, and (optionally) a SystemCondition for the background task. Этот метод возвращает объект BackgroundTaskRegistration.This method returns a BackgroundTaskRegistration object.

Важно!

taskEntryPoint — для фоновых задач, которые выполняются вне процесса, это имя должно быть составлено в виде имени пространства имен, "." и имени класса, содержащего ваш фоновый класс.taskEntryPoint - for background tasks that run in out of process, this must be constructed as the namespace name, '.', and the name of the class containing your background class. Строка обрабатывается с учетом регистра.The string is case-sensitive. Например, если имеется пространство имен "MyBackgroundTasks" и класс "BackgroundTask1", содержащий код вашего класса фоновой задачи, строка для taskEntryPoint имела бы вид "MyBackgroundTasks.BackgroundTask1".For example, if you had a namespace "MyBackgroundTasks" and a class "BackgroundTask1" that contained your background class code, the string for taskEntryPoint would be "MyBackgroundTasks.BackgroundTask1". Если фоновая задача выполняется в том же процессе, что и приложение (т. е. представляет собой внутрипроцессную фоновую задачу), taskEntryPoint задавать не нужно.If your background task runs in the same process as your app (i.e. a in-process background task) taskEntryPoint should not be set.

public static BackgroundTaskRegistration RegisterBackgroundTask(
                                                string taskEntryPoint,
                                                string name,
                                                IBackgroundTrigger trigger,
                                                IBackgroundCondition condition)
{
    
    // We'll add code to this function in subsequent steps.

}
BackgroundTaskRegistration^ MainPage::RegisterBackgroundTask(
                                             Platform::String ^ taskEntryPoint,
                                             Platform::String ^ taskName,
                                             IBackgroundTrigger ^ trigger,
                                             IBackgroundCondition ^ condition)
{
    
    // We'll add code to this function in subsequent steps.

}

Проверка наличия существующих регистрацийCheck for existing registrations

Проверьте, не зарегистрирована ли уже задача.Check whether the task is already registered. Это важно проверить, потому что при многократной регистрации задачи она будет выполняться несколько раз при каждом срабатывании триггера, что может привести к избыточному потреблению ресурсов ЦП и непредсказуемому поведению.It's important to check this because if a task is registered multiple times, it will run more than once whenever it’s triggered; this can use excess CPU and may cause unexpected behavior.

Для проверки наличия существующих регистраций можно запросить свойство BackgroundTaskRegistration.AllTasks и выполнить итерацию по результату.You can check for existing registrations by querying the BackgroundTaskRegistration.AllTasks property and iterating on the result. Проверьте имя каждого экземпляра: если оно совпадает с именем регистрируемой задачи, следует прервать цикл и установить переменную флага, чтобы вашему коду удалось выбрать другой путь в следующем шаге.Check the name of each instance – if it matches the name of the task you’re registering, then break out of the loop and set a flag variable so that your code can choose a different path in the next step.

Примечание    . Используйте имена фоновых задач, которые являются уникальными для приложения.Note  Use background task names that are unique to your app. Убедитесь, что каждая фоновая задача имеет уникальное имя.Ensure each background task has a unique name.

Следующий код регистрирует фоновую задачу с использованием триггера SystemTrigger, который мы создали в последнем шаге:The following code registers a background task using the SystemTrigger we created in the last step:

public static BackgroundTaskRegistration RegisterBackgroundTask(
                                                string taskEntryPoint,
                                                string name,
                                                IBackgroundTrigger trigger,
                                                IBackgroundCondition condition)
{
    //
    // Check for existing registrations of this background task.
    //

    foreach (var cur in BackgroundTaskRegistration.AllTasks)
    {

        if (cur.Value.Name == name)
        {
            //
            // The task is already registered.
            //

            return (BackgroundTaskRegistration)(cur.Value);
        }
    }
    
    // We'll register the task in the next step.
}
BackgroundTaskRegistration^ MainPage::RegisterBackgroundTask(
                                             Platform::String ^ taskEntryPoint,
                                             Platform::String ^ taskName,
                                             IBackgroundTrigger ^ trigger,
                                             IBackgroundCondition ^ condition)
{
    //
    // Check for existing registrations of this background task.
    //
    
    auto iter   = BackgroundTaskRegistration::AllTasks->First();
    auto hascur = iter->HasCurrent;
    
    while (hascur)
    {
        auto cur = iter->Current->Value;
        
        if(cur->Name == name)
        {
            //
            // The task is registered.
            //
            
            return (BackgroundTaskRegistration ^)(cur);
        }
        
        hascur = iter->MoveNext();
    }
    
    // We'll register the task in the next step.
}

Регистрация фоновой задачи (или возврат существующей регистрации)Register the background task (or return the existing registration)

Проверьте, не найдена ли задача в списке существующих регистраций фоновых задач.Check to see if the task was found in the list of existing background task registrations. Если да, верните этот экземпляр задачи.If so, return that instance of the task.

Затем зарегистрируйте задачу с использованием нового объекта BackgroundTaskBuilder.Then, register the task using a new BackgroundTaskBuilder object. Этот код должен проверить, имеет ли параметр условия значение NULL, и, если нет, добавить условие к объекту регистрации.This code should check whether the condition parameter is null, and if not, add the condition to the registration object. Верните объект BackgroundTaskRegistration, возвращенный методом BackgroundTaskBuilder.Register.Return the BackgroundTaskRegistration returned by the BackgroundTaskBuilder.Register method.

Примечание    . Параметры регистрации фоновой задачи проверяются во время регистрации.Note  Background task registration parameters are validated at the time of registration. Если какие-либо из параметров регистрации недопустимы, возвращается ошибка.An error is returned if any of the registration parameters are invalid. Убедитесь, что ваше приложение корректно обрабатывает сценарии, в которых регистрация фоновой задачи завершается ошибкой. Если работа вашего приложения зависит от наличия допустимого объекта регистрации после попытки регистрации задачи, то оно может дать сбой.Ensure that your app gracefully handles scenarios where background task registration fails - if instead your app depends on having a valid registration object after attempting to register a task, it may crash. Примечание. Если вы регистрируете фоновую задачу, которая выполняется в том же процессе, что и приложение, отправьте String.Empty или null для параметра taskEntryPoint.Note If you are registering a background task that runs in the same process as your app, send String.Empty or null for the taskEntryPoint parameter.

В следующем примере выполняется либо возврат существующей задачи, либо добавление кода, регистрирующего фоновую задачу (включая дополнительное условие системы, если оно есть):The following example either returns the existing task, or adds code that registers the background task (including the optional system condition if present):

public static BackgroundTaskRegistration RegisterBackgroundTask(
                                                string taskEntryPoint,
                                                string name,
                                                IBackgroundTrigger trigger,
                                                IBackgroundCondition condition)
{
    //
    // Check for existing registrations of this background task.
    //

    foreach (var cur in BackgroundTaskRegistration.AllTasks)
    {

        if (cur.Value.Name == taskName)
        {
            //
            // The task is already registered.
            //

            return (BackgroundTaskRegistration)(cur.Value);
        }
    }

    //
    // Register the background task.
    //

    var builder = new BackgroundTaskBuilder();

    builder.Name = name;

    // in-process background tasks don't set TaskEntryPoint
    if ( taskEntryPoint != null && taskEntryPoint != String.Empty)
    {
        builder.TaskEntryPoint = taskEntryPoint;
    }
    builder.SetTrigger(trigger);

    if (condition != null)
    {
        builder.AddCondition(condition);
    }

    BackgroundTaskRegistration task = builder.Register();

    return task;
}
BackgroundTaskRegistration^ MainPage::RegisterBackgroundTask(
                                             Platform::String ^ taskEntryPoint,
                                             Platform::String ^ taskName,
                                             IBackgroundTrigger ^ trigger,
                                             IBackgroundCondition ^ condition)
{

    //
    // Check for existing registrations of this background task.
    //

    auto iter   = BackgroundTaskRegistration::AllTasks->First();
    auto hascur = iter->HasCurrent;

    while (hascur)
    {
        auto cur = iter->Current->Value;

        if(cur->Name == name)
        {
            //
            // The task is registered.
            //

            return (BackgroundTaskRegistration ^)(cur);
        }

        hascur = iter->MoveNext();
    }

    //
    // Register the background task.
    //

    auto builder = ref new BackgroundTaskBuilder();

    builder->Name = name;
    builder->TaskEntryPoint = taskEntryPoint;
    builder->SetTrigger(trigger);

    if (condition != nullptr) {
        
        builder->AddCondition(condition);
    }

    BackgroundTaskRegistration ^ task = builder->Register();

    return task;
}

Полная служебная функция регистрации фоновой задачиComplete background task registration utility function

Этот пример демонстрирует полную функцию регистрации фоновой задачи.This example shows the completed background task registration function. Эту функцию можно использовать для регистрации большинства фоновых задач, за исключением сетевых.This function can be used to register most background tasks, with the exception of networking background tasks.

//
// Register a background task with the specified taskEntryPoint, name, trigger,
// and condition (optional).
//
// taskEntryPoint: Task entry point for the background task.
// taskName: A name for the background task.
// trigger: The trigger for the background task.
// condition: Optional parameter. A conditional event that must be true for the task to fire.
//
public static BackgroundTaskRegistration RegisterBackgroundTask(string taskEntryPoint,
                                                                string taskName,
                                                                IBackgroundTrigger trigger,
                                                                IBackgroundCondition condition)
{
    //
    // Check for existing registrations of this background task.
    //

    foreach (var cur in BackgroundTaskRegistration.AllTasks)
    {

        if (cur.Value.Name == taskName)
        {
            //
            // The task is already registered.
            //

            return (BackgroundTaskRegistration)(cur.Value);
        }
    }

    //
    // Register the background task.
    //

    var builder = new BackgroundTaskBuilder();

    builder.Name = taskName;
    builder.TaskEntryPoint = taskEntryPoint;
    builder.SetTrigger(trigger);

    if (condition != null)
    {

        builder.AddCondition(condition);
    }

    BackgroundTaskRegistration task = builder.Register();

    return task;
}
//
// Register a background task with the specified taskEntryPoint, name, trigger,
// and condition (optional).
//
// taskEntryPoint: Task entry point for the background task.
// taskName: A name for the background task.
// trigger: The trigger for the background task.
// condition: Optional parameter. A conditional event that must be true for the task to fire.
//
BackgroundTaskRegistration^ MainPage::RegisterBackgroundTask(Platform::String ^ taskEntryPoint,
                                                             Platform::String ^ taskName,
                                                             IBackgroundTrigger ^ trigger,
                                                             IBackgroundCondition ^ condition)
{

    //
    // Check for existing registrations of this background task.
    //

    auto iter   = BackgroundTaskRegistration::AllTasks->First();
    auto hascur = iter->HasCurrent;

    while (hascur)
    {
        auto cur = iter->Current->Value;

        if(cur->Name == name)
        {
            //
            // The task is registered.
            //

            return (BackgroundTaskRegistration ^)(cur);
        }

        hascur = iter->MoveNext();
    }


    //
    // Register the background task.
    //

    auto builder = ref new BackgroundTaskBuilder();

    builder->Name = name;
    builder->TaskEntryPoint = taskEntryPoint;
    builder->SetTrigger(trigger);

    if (condition != nullptr) {

        builder->AddCondition(condition);
    }

    BackgroundTaskRegistration ^ task = builder->Register();

    return task;
}