Edit

Share via


Background task migration strategy

Background tasks are used heavily in UWP apps for performing jobs when a particular trigger is invoked on the machine. As these don’t require any service to be running listening for the triggers, it's very power efficient. So, while migrating UWP apps to WinUI 3 and other desktop apps that use Windows App SDK, developers may require support for implementing background tasks on the platform.

Background tasks offered in the UWP app model can either be out-of-proc or in-proc. This article describes the migration strategy for each of these types when moving to BackgroundTaskBuilder APIs in Windows App SDK.

Out-of-proc background tasks

In the case of out-of-proc background tasks in UWP, background tasks will be written as a Windows Runtime (WinRT) component, and the component is set as the TaskEntryPoint on BackgroundTaskBuilder during registration. While migrating to Windows App SDK, developers can keep this as-is and package the WinRT component together with the desktop project. In this case, the broker infrastructure will be launching backgroundtaskhost process when the trigger is invoked, and the WinRT component background task would be executed in the process. In this approach, the background task would be running in a Low Integrity Level (IL) process (backgroundtaskhost.exe) while the main desktop project would be running in a Medium IL process.

If the application needs to to run a background task in a medium IL process itself, the full trust COM component needs to be used for background tasks. In that scenario, developers must use the Windows App SDK BackgroundTaskBuilder to register the full trust COM component. Note that the BackgroundTaskBuilder API from the Windows.ApplicationModel.Background namespace will throw exceptions while registering of some of the triggers.

A full WinUI 3 background task registration sample can be found on GitHub.

More details on the implementation are available here. The only required change would be to replace the WinRT BackgroundTaskBuilder API with the Windows App SDK API Microsoft.Windows.ApplicationModel.Background.BackgroundTaskBuilder.

In-proc background tasks

For in-proc background tasks in UWP, background task routines are implemented in the OnBackgroundActivated callback which runs as part of the foreground process. This won't be possible in a WinUI 3 application as the OnBackgroundActivated callbacks aren't available. The application needs to move the background task implementations to full trust COM tasks as described above and define the COM server in the package manifest to handle the COM activation of the task. When the trigger occurs, COM activation will happen on the corresponding COM Coclass registered for the trigger.

A full WinUI 3 background task registration sample can be found on GitHub.

More details on the implementation are available here. The only change would be to replace the WinRT BackgroundTaskBuilder API with the Windows App SDK APIs in Microsoft.Windows.ApplicationModel.Background.BackgroundTaskBuilder.

Windows App SDK BackgroundTaskBuilder API

This Windows App SDK BackgroundTaskBuilder API is created to support the full trust COM background task implementations in WinUI 3 and other desktop applications that use Windows App SDK, as the WinRT API throws exceptions during registration except for a few triggers.

The following code shows how to register background task using Windows App SDK BackgroundTaskBuilder APIs:

//Using Windows App SDK API for BackgroundTaskBuilder
winrt::Microsoft::Windows::ApplicationModel::Background::BackgroundTaskBuilder builder;
SystemTrigger trigger = SystemTrigger(SystemTriggerType::TimeZoneChange, false);
auto backgroundTrigger = trigger.as<IBackgroundTrigger>();
builder.SetTrigger(backgroundTrigger);
builder.AddCondition(SystemCondition(SystemConditionType::InternetAvailable));
builder.SetTaskEntryPointClsid(classGuid);
builder.Register();

The following is the equivalent C# code:

// Using Windows App SDK API for BackgroundTaskBuilder
var builder = new Microsoft.Windows.ApplicationModel.Background.BackgroundTaskBuilder();
var trigger = new SystemTrigger(SystemTriggerType.TimeZoneChange, false);
builder.SetTrigger(trigger);
builder.AddCondition(new SystemCondition(SystemConditionType.InternetAvailable));
builder.SetTaskEntryPointClsid(classGuid);
builder.Register();

To use this API, add the tag below to the project file to enable Windows App SDK background tasks:

<WindowsAppSDKBackgroundTask>true</WindowsAppSDKBackgroundTask>

Also, in the manifest file, the EntryPoint for BackgroundTask is set to Microsoft.Windows.ApplicationModel.Background.UniversalBGTask.Task:

<Extension Category="windows.backgroundTasks" EntryPoint="Microsoft.Windows.ApplicationModel.Background.UniversalBGTask.Task">
    <BackgroundTasks>
        <Task Type="general"/>
    </BackgroundTasks>
</Extension>

For C# applications, an ActivatableClass registration should also be added to the manifest file:

<Extension Category="windows.activatableClass.inProcessServer">
    <InProcessServer>
        <Path>Microsoft.Windows.ApplicationModel.Background.UniversalBGTask.dll</Path>
        <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.Background.UniversalBGTask.Task" ThreadingModel="both"/>
    </InProcessServer>
</Extension>

Leveraging TaskScheduler for background task migration

Task Scheduler helps desktop apps achieve the same functionality that is provided by BackgroundTaskBuilder in UWP apps. More details on implementations using TaskScheduler are available here.

ApplicationTrigger use in Windows App SDK applications

ApplicationTrigger is supported in UWP applications due to the lifetime management scenario where the application process can be suspended. This scenario does not occur for WinUI and other Windows App SDK desktop applications, so this trigger is not supported in WinUI applications. All logic related to ApplicationTrigger will need to be rewritten to execute by launching another process or by running in a thread pool thread. For more information, see CreateThread and CreateProcess.