Crear y registrar una tarea en segundo plano fuera del procesoCreate and register an out-of-process background task

API importantesImportant APIs

Crea una tarea en segundo plano y regístrala para ejecutarla cuando tu aplicación no esté en primer plano.Create a background task class and register it to run when your app is not in the foreground. Este tema muestra cómo crear y registrar una tarea en segundo plano que se ejecuta en un proceso independiente al proceso de aplicación.This topic demonstrates how to create and register a background task that runs in a separate process than your app's process. Para efectuar un trabajo en segundo plano directamente en la aplicación en primer plano, consulta Crear y registrar una tarea en segundo plano dentro del proceso.To do background work directly in the foreground application, see Create and register an in-process background task.

Nota

Si usas una tarea en segundo plano para reproducir contenido multimedia en segundo plano, consulta Reproducir elementos multimedia en segundo plano para obtener información sobre las mejoras en Windows 10, versión 1607, que lo hacen mucho más fácil.If you use a background task to play media in the background, see Play media in the background for information about improvements in Windows 10, version 1607, that make it much easier.

Creación de la clase de tareas en segundo planoCreate the Background Task class

Puedes ejecutar código en segundo plano escribiendo clases que implementen la interfaz IBackgroundTask.You can run code in the background by writing classes that implement the IBackgroundTask interface. Este código se ejecuta cuando se desencadena un evento específico mediante, por ejemplo, SystemTrigger o MaintenanceTrigger.This code runs when a specific event is triggered by using, for example, SystemTrigger or MaintenanceTrigger.

En estos pasos te mostramos cómo escribir una nueva clase que implemente la interfaz IBackgroundTask.The following steps show you how to write a new class that implements the IBackgroundTask interface.

  1. Crea un nuevo proyecto para tareas en segundo plano y agrégalo a tu solución.Create a new project for background tasks and add it to your solution. Para ello, haga clic con el botón derecho en el nodo de la solución en el Explorador de soluciones y seleccione Agregar > nuevo proyecto.To do this, right-click on your solution node in the Solution Explorer and select Add > New Project. Después, seleccione el tipo de proyecto de componente de Windows Runtime , asigne un nombre al proyecto y haga clic en Aceptar.Then select the Windows Runtime Component project type, name the project, and click OK.
  2. Haz referencia al proyecto de tareas en segundo plano desde tu proyecto de aplicación de la Plataforma universal de Windows (UWP).Reference the background tasks project from your Universal Windows Platform (UWP) app project. En el caso de una aplicación de C# o C++, en el proyecto de la aplicación, haga clic con el botón derecho en referencias y seleccione Agregar nueva referencia.For a C# or C++ app, in your app project, right-click on References and select Add New Reference. En Solución, selecciona Proyectos, selecciona el nombre de tu proyecto de tarea en segundo plano y haz clic en Aceptar.Under Solution, select Projects and then select the name of your background task project and click Ok.
  3. En el proyecto de tareas en segundo plano, agregue una nueva clase que implemente la interfaz IBackgroundTask .To the background tasks project, add a new class that implements the IBackgroundTask interface. El método IBackgroundTask. Run es un punto de entrada necesario al que se llamará cuando se desencadene el evento especificado. Este método es necesario en cada tarea en segundo plano.The IBackgroundTask.Run method is a required entry point that will be called when the specified event is triggered; this method is required in every background task.

Nota

La propia clase de tarea en segundo plano — y todas las demás clases del proyecto de tarea en segundo plano — deben ser clases públicas que estén selladas (o finales).The background task class itself—and all other classes in the background task project—need to be public classes that are sealed (or final).

En el código de ejemplo siguiente se muestra un punto de partida muy básico para una clase de tarea en segundo plano.The following sample code shows a very basic starting point for a background task class.

// 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)
{
}
  1. Si ejecutas algún código asincrónico en tu tarea en segundo plano, entonces esta necesita usar un aplazamiento.If you run any asynchronous code in your background task, then your background task needs to use a deferral. Si no usa un aplazamiento, el proceso de la tarea en segundo plano puede finalizar inesperadamente si el método Run vuelve antes de que se haya ejecutado cualquier trabajo asincrónico hasta que finalice.If you don't use a deferral, then the background task process can terminate unexpectedly if the Run method returns before any asynchronous work has run to completion.

Solicite el aplazamiento en el método de ejecución antes de llamar al método asincrónico.Request the deferral in the Run method before calling the asynchronous method. Guarde el aplazamiento en un miembro de datos de clase para que se pueda obtener acceso a él desde el método asincrónico.Save the deferral to a class data member so that it can be accessed from the asynchronous method. Declara el aplazamiento completo después de que se complete el código asincrónico.Declare the deferral complete after the asynchronous code completes.

En el código de ejemplo siguiente se obtiene el aplazamiento, se guarda y se libera cuando se completa el código asincrónico.The following sample code gets the deferral, saves it, and releases it when the asynchronous code is complete.

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

Nota

En C#, se llama a los métodos asincrónicos de la tarea en segundo plano mediante las palabras clave async/await.In C#, your background task's asynchronous methods can be called using the async/await keywords. En C++/CX, se puede lograr un resultado similar mediante el uso de una cadena de tareas.In C++/CX, a similar result can be achieved by using a task chain.

Para más información acerca de los modelos asincrónicos, consulta el tema sobre la Programación asincrónica.For more information about asynchronous patterns, see Asynchronous programming. Para obtener más ejemplos sobre cómo usar aplazamientos para evitar que una tarea en segundo plano termine antes de tiempo, consulta la muestra de tarea en segundo plano.For additional examples of how to use deferrals to keep a background task from stopping early, see the background task sample.

Los siguientes pasos se completan en una de tus clases de aplicaciones (por ejemplo, MainPage.xaml.cs).The following steps are completed in one of your app classes (for example, MainPage.xaml.cs).

Nota

También puede crear una función dedicada para registrar tareas en segundo plano — . consulte registrar una tarea en segundo plano.You can also create a function dedicated to registering background tasks—see Register a background task. En ese caso, en lugar de usar los tres pasos siguientes, puede simplemente construir el desencadenador y proporcionarlo a la función de registro junto con el nombre de tarea, el punto de entrada de tarea y, opcionalmente, una condición.In that case, instead of using the next three steps, you can simply construct the trigger and provide it to the registration function along with the task name, task entry point, and (optionally) a condition.

Registrar la tarea en segundo plano por ejecutarRegister the background task to run

  1. Averigüe si la tarea en segundo plano ya está registrada recorriendo en iteración la propiedad BackgroundTaskRegistration. AllTasks .Find out whether the background task is already registered by iterating through the BackgroundTaskRegistration.AllTasks property. Este paso es importante; si tu aplicación no comprueba los registros de tareas en segundo plano existentes, fácilmente podría registrar una tarea varias veces. Esto causaría problemas de rendimiento y consumiría el tiempo de CPU disponible para la tarea antes de que su trabajo pueda completarse.This step is important; if your app doesn't check for existing background task registrations, it could easily register the task multiple times, causing issues with performance and maxing out the task's available CPU time before work can complete.

En el ejemplo siguiente se recorre en iteración la propiedad AllTasks y se establece una variable de marca en true si la tarea ya está registrada.The following example iterates on the AllTasks property and sets a flag variable to true if the task is already registered.

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();
}
  1. Si aún no está registrada, usa BackgroundTaskBuilder para crear una instancia de la tarea en segundo plano.If the background task is not already registered, use BackgroundTaskBuilder to create an instance of your background task. El punto de entrada de la tarea debe ser el nombre de tu clase de tarea en segundo plano con el espacio de nombres como prefijo.The task entry point should be the name of your background task class prefixed by the namespace.

El desencadenador de tarea en segundo plano controla cuándo se ejecutará la tarea en segundo plano.The background task trigger controls when the background task will run. Para obtener una lista de posibles desencadenadores del sistema, consulta SystemTrigger.For a list of possible triggers, see SystemTrigger.

Por ejemplo, este código crea una nueva tarea en segundo plano y la establece para que se ejecute cuando se produce el desencadenador TimeZoneChanged :For example, this code creates a new background task and sets it to run when the TimeZoneChanged trigger occurs:

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));
  1. Puedes agregar una condición para controlar si la tarea se ejecutará después de que se produzca el evento del desencadenador (opcional).You can add a condition to control when your task will run after the trigger event occurs (optional). Por ejemplo, si no quieres que la tarea se ejecute hasta que el usuario esté presente, usa la condición UserPresent.For example, if you don't want the task to run until the user is present, use the condition UserPresent. Para obtener una lista de posibles condiciones, consulta SystemConditionType.For a list of possible conditions, see SystemConditionType.

El siguiente código de muestra asigna una condición que requiere que el usuario esté presente:The following sample code assigns a condition requiring the user to be present:

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));
  1. Registra la tarea en segundo plano llamando al método Register en el objeto BackgroundTaskBuilder.Register the background task by calling the Register method on the BackgroundTaskBuilder object. Almacena el resultado de BackgroundTaskRegistration para usarlo en el siguiente paso.Store the BackgroundTaskRegistration result so it can be used in the next step.

El siguiente código registra la tarea en segundo plano y almacena el resultado:The following code registers the background task and stores the result:

BackgroundTaskRegistration task = builder.Register();
Windows::ApplicationModel::Background::BackgroundTaskRegistration task{ builder.Register() };
BackgroundTaskRegistration^ task = builder->Register();

Nota

Las aplicaciones universales de Windows deben llamar a RequestAccessAsync antes de registrar cualquier tipo de desencadenador en segundo plano.Universal Windows apps must call RequestAccessAsync before registering any of the background trigger types.

Para garantizar que tu aplicación universal de Windows continúe funcionando correctamente después de publicar una actualización, usa el desencadenador ServicingComplete (consulta SystemTriggerType) para realizar los cambios de configuración posteriores a la actualización como la migración de la base de datos de la aplicación y el registro de tareas en segundo plano.To ensure that your Universal Windows app continues to run properly after you release an update, use the ServicingComplete (see SystemTriggerType) trigger to perform any post-update configuration changes such as migrating the app's database and registering background tasks. Es recomendable anular el registro de tareas en segundo plano asociadas con la versión anterior de la aplicación (consulta RemoveAccess) y registrar las tareas en segundo plano para la nueva versión de la aplicación (consulta RequestAccessAsync) en este momento.It is best practice to unregister background tasks associated with the previous version of the app (see RemoveAccess) and register background tasks for the new version of the app (see RequestAccessAsync) at this time.

Para obtener más información, vea instrucciones para tareas en segundo plano.For more information, see Guidelines for background tasks.

Controlar la finalización de tareas en segundo plano mediante controladores de eventosHandle background task completion using event handlers

Debes registrar un método con BackgroundTaskCompletedEventHandler, de manera que tu aplicación pueda obtener resultados de la tarea en segundo plano.You should register a method with the BackgroundTaskCompletedEventHandler, so that your app can get results from the background task. Cuando la aplicación se inicia o se reanuda, se llama al método marcado si la tarea en segundo plano se ha completado desde la última vez que la aplicación estuvo en primer plano.When the app is launched or resumed, the marked method will be called if the background task has completed since the last time the app was in the foreground. (Se llamará de forma inmediata al método OnCompleted si la tarea en segundo plano se completa mientras tu aplicación se encuentra actualmente en primer plano).(The OnCompleted method will be called immediately if the background task completes while your app is currently in the foreground.)

  1. Escribe un método OnCompleted para administrar la finalización de tareas en segundo plano.Write an OnCompleted method to handle the completion of background tasks. Por ejemplo, el resultado de la tarea en segundo plano podría provocar una actualización de la interfaz de usuario.For example, the background task result might cause a UI update. La superficie del método que se muestra aquí es necesaria para el método del controlador de eventos OnCompleted, incluso aunque este ejemplo no usa el parámetro args.The method footprint shown here is required for the OnCompleted event handler method, even though this example does not use the args parameter.

La siguiente muestra de código reconoce la finalización de la tarea en segundo plano y llama a un método de ejemplo de actualización de la interfaz de usuario que toma una cadena de mensaje.The following sample code recognizes background task completion and calls an example UI update method that takes a message string.

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

Nota

Las actualizaciones de la interfaz de usuario se deberían realizar de forma asincrónica, para evitar retener el subproceso de interfaz de usuario.UI updates should be performed asynchronously, to avoid holding up the UI thread. Para ver un ejemplo, consulta el método UpdateUI en la muestra de tarea en segundo plano.For an example, see the UpdateUI method in the background task sample.

  1. Vuelve al punto en el que registraste la tarea en segundo plano.Go back to where you registered the background task. Después de la línea de código, agrega un nuevo objeto BackgroundTaskCompletedEventHandler.After that line of code, add a new BackgroundTaskCompletedEventHandler object. Proporciona tu método OnCompleted como parámetro para el constructor BackgroundTaskCompletedEventHandler.Provide your OnCompleted method as the parameter for the BackgroundTaskCompletedEventHandler constructor.

La siguiente muestra de código agrega un constructor BackgroundTaskCompletedEventHandler a BackgroundTaskRegistration:The following sample code adds a BackgroundTaskCompletedEventHandler to the BackgroundTaskRegistration:

task.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);
task.Completed({ this, &MainPage::OnCompleted });
task->Completed += ref new BackgroundTaskCompletedEventHandler(this, &MainPage::OnCompleted);

Declare en el manifiesto de la aplicación que la aplicación usa tareas en segundo planoDeclare in the app manifest that your app uses background tasks

Antes de que tu aplicación pueda ejecutar tareas en segundo plano, debes declarar cada una de ellas en el manifiesto de la aplicación.Before your app can run background tasks, you must declare each background task in the app manifest. Si la aplicación intenta registrar una tarea en segundo plano con un desencadenador que no aparece en el manifiesto, se producirá un error en el registro de la tarea en segundo plano con el error "tiempo de ejecución de clase no registrado".If your app attempts to register a background task with a trigger that isn't listed in the manifest, the registration of the background task will fail with a "runtime class not registered" error.

  1. Abre el diseñador de manifiestos del paquete. Para ello, abre el archivo Package.appxmanifest.Open the package manifest designer by opening the file named Package.appxmanifest.
  2. Abre la pestaña Declaraciones.Open the Declarations tab.
  3. Desde la lista desplegable Declaraciones disponibles, selecciona Tareas en segundo plano y haz clic en Agregar.From the Available Declarations drop-down, select Background Tasks and click Add.
  4. Activa la casilla Evento del sistema.Select the System event checkbox.
  5. En el cuadro de texto punto de entrada: , escriba el espacio de nombres y el nombre de la clase en segundo plano que se va a realizar en este ejemplo es Tasks. ExampleBackgroundTask.In the Entry point: textbox, enter the namespace and name of your background class which is for this example is Tasks.ExampleBackgroundTask.
  6. Cierra el diseñador de manifiesto.Close the manfiest designer.

Se añadirá el siguiente elemento Extensions al archivo Package.appxmanifest para registrar la tarea en segundo plano:The following Extensions element is added to your Package.appxmanifest file to register the background task:

<Extensions>
  <Extension Category="windows.backgroundTasks" EntryPoint="Tasks.ExampleBackgroundTask">
    <BackgroundTasks>
      <Task Type="systemEvent" />
    </BackgroundTasks>
  </Extension>
</Extensions>

Resumen y pasos siguientesSummary and next steps

Ahora deberías conocer los conceptos básicos de cómo escribir una clase de tareas en segundo plano, cómo registrar la tarea en segundo plano desde dentro de tu aplicación y cómo hacer que tu aplicación reconozca cuándo se ha completado la tarea en segundo plano.You should now understand the basics of how to write a background task class, how to register the background task from within your app, and how to make your app recognize when the background task is complete. También deberías comprender cómo actualizar el manifiesto de la aplicación para que la aplicación pueda registrar correctamente la tarea en segundo plano.You should also understand how to update the application manifest so that your app can successfully register the background task.

Nota

Descarga la muestra de tarea en segundo plano para ver ejemplos de código similares en el contexto de una aplicación para UWP completa y robusta que usa tareas en segundo plano.Download the background task sample to see similar code examples in the context of a complete and robust UWP app that uses background tasks.

Consulta los siguientes temas relacionados para obtener referencia de las API, una guía conceptual sobre tareas en segundo plano e instrucciones más detalladas para escribir aplicaciones que usan tareas en segundo plano.See the following related topics for API reference, background task conceptual guidance, and more detailed instructions for writing apps that use background tasks.

Temas con instrucciones detalladas sobre las tareas en segundo planoDetailed background task instructional topics

Guía de tareas en segundo planoBackground task guidance

Referencia de API de tareas en segundo planoBackground Task API Reference