Registrar una tarea en segundo plano

API importantes

Aprende a crear una función que pueda reutilizarse para registrar de forma segura la mayoría de las tareas en segundo plano.

Este tema se aplica a las tareas en segundo plano dentro de proceso y a las tareas en segundo plano fuera de proceso. En este tema suponemos que ya tienes una tarea en segundo plano que debe registrarse. (Consulta Crear y registrar una tarea en segundo plano fuera de proceso o Crear y registrar una tarea en segundo plano dentro de proceso para obtener información sobre cómo escribir una tarea en segundo plano).

En este tema se recorre una función de utilidad que registra tareas en segundo plano. Antes de registrar una tarea varias veces, esta función de utilidad primero comprueba registros existentes para evitar los problemas que pueden surgir por registros repetidos. Además puede aplicar una condición del sistema a la tarea en segundo en plano. El tutorial incluye un ejemplo completo de funcionamiento de esta función de utilidad.

Note  

Las aplicaciones universales de Windows deben llamar a RequestAccessAsync antes de registrar cualquier tipo de desencadenador en segundo plano.

Para garantizar que la aplicación universal de Windows continúe funcionando correctamente después de publicar una actualización, se debe llamar a RemoveAccess y luego a RequestAccessAsync cuando se inicia la aplicación tras su actualización. Para obtener más información, vea Directrices para tareas en segundo plano.

Definir el tipo de devolución y la firma del método

Este método toma el punto de entrada de la tarea, el nombre de la tarea y un desencadenador de tarea en segundo plano preconstruido y, de forma opcional, un objeto SystemCondition para la tarea en segundo plano. Este método devuelve un objeto BackgroundTaskRegistration.

Importante

taskEntryPoint - para las tareas en segundo plano que se ejecutan fuera del proceso, se debe construir como el nombre del espacio de nombres, '.' y el nombre de la clase que contiene la clase en segundo plano. La cadena distingue mayúsculas de minúsculas. Por ejemplo, si tenía un espacio de nombres "MyBackgroundTasks" y una clase "BackgroundTask1" que contenía el código de clase en segundo plano, la cadena para taskEntryPoint sería "MyBackgroundTasks.BackgroundTask1". Si la tarea en segundo plano se ejecuta en el mismo proceso que la aplicación (es decir, una tarea en segundo plano en proceso), no se debe establecer taskEntryPoint.

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.

}

Comprobar registros existentes

Comprueba si la tarea ya está registrada. Es importante que compruebes esto porque si una tarea está registrada varias veces, se ejecutará más de una vez cada vez que sea desencadenada; esto hace un consumo excesivo de CPU y puede ocasionar un comportamiento inesperado.

Puedes comprobar registros existentes consultando la propiedad BackgroundTaskRegistration.AllTasks e iterando en el resultado. Comprueba el nombre de cada instancia. Si coincide con el nombre de la tarea que estás registrando, entonces interrumpe el bucle y coloca una variable de marca para que tu código pueda elegir otra ruta en el siguiente paso.

Nota Usa nombres de tareas en segundo plano que son únicos para tu aplicación. Asegúrate de que cada tarea en segundo plano tenga un nombre exclusivo.

El siguiente código registra una tarea en segundo plano usando SystemTrigger, que creamos en el último paso:

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.
}

Registrar la tarea en segundo plano (o devolver el registro existente)

Comprueba si se encontró la tarea en la lista de registros de tareas en segundo plano existentes. Si ya está en la lista, devuelve esa instancia de la tarea.

Después registra la tarea con un nuevo objeto BackgroundTaskBuilder. Este código debe comprobar si el parámetro de la condición es nulo y, si no lo es, agregar la condición al objeto de registro. Devuelve el BackgroundTaskRegistration devuelto por el método BackgroundTaskBuilder.Register.

Nota Los parámetros de registro de tareas en segundo plano se validan en el momento del registro. Se devuelve un error si cualquiera de los parámetros de registro no es válido. Asegúrate de que la aplicación se ocupe correctamente de los escenarios en los que se produce un error en el registro de tareas en segundo plano. Si, en cambio, la aplicación depende de que haya un objeto de registro válido después de intentar registrar una tarea, es posible que se bloquee. Nota Si vas a registrar una tarea en segundo plano que se ejecuta en el mismo proceso que la aplicación, envía String.Empty o null para el parámetro taskEntryPoint.

El siguiente ejemplo, o bien devuelve la tarea existente, o bien agrega código que registra la tarea en segundo plano (incluida la condición del sistema opcional si la hubiera):

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;
}

Completar la función de utilidad de registro de tareas en segundo plano

Ese ejemplo muestra la función de registro de tareas en segundo plano completa. Esta función puede usarse para registrar la mayoría de las tareas en segundo plano, a excepción de las tareas en red.

//
// 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;
}