Регистрация и запуск задачи

Последнее обновление: 02.03.2016

После определения фоновой задачи, ее надо зарегистрировать в основном проекте, и после этого она будет готова для запуска.

Первым делом надо определить в файле манифеста приложения тип задачи. Для этого после открытия файла манифеста перейдем на вкладку Declarations. На этой вкладке в поле Available Declarations выберем пункт Background Tasks и нажмем на кнопку Add. После этого в поле Supported Declarations внизу должен быть добавлен соответствующий пункт.

В центральной части в разделе Properties определим тип задачи General, а внизу в поле Entry point впишем полное название нашего класса фоновой задачи: MyRuntimeComponent.MyBackgroundTask.

Регистрация задачи в файле манифеста в UWP

Так как у нас задача общего характера, то определяем для тип именно General, однако в зависимости от характера задачи ее тип может быть иным. Например, при работе со звуком нам надо выбрать тип Audio. Либо, если мы хотим, чтобы задача запускалась по таймеру, то надо выбрать тип Timer.

Далее определим простейший визуальный интерфейс для приложения:

<Page
    x:Class="BackgroundTaskApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BackgroundTaskApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>
        <Style TargetType="Button">
            <Setter Property="Margin" Value="50 10 50 10" />
            <Setter Property="Height" Value="30" />
            <Setter Property="Width" Value="90" />
        </Style>
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TextBlock x:Name="outputBlock" />
        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Name="startButton" Content="Start" Click="Start_Click" />
            <Button Name="stopButton" IsEnabled="False" Content="Stop" Click="Stop_Click"  />
        </StackPanel>
    </Grid>
</Page>

На форме будет текстовое поле для вывода результатов и кнопки для управления задачей.

Теперь в файле кода определим обработчики для кнопок:

using System;
using System.Linq;
using Windows.ApplicationModel.Background;
using Windows.Storage;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace BackgroundTaskApp
{
    public sealed partial class MainPage : Page
    {
        string taskName = "factorial";
        
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Start_Click(object sender, RoutedEventArgs e)
        {
            ApplicationData.Current.LocalSettings.Values["number"] = 6; // число для подсчета факториала
            var taskList = BackgroundTaskRegistration.AllTasks.Values;
            var task = taskList.FirstOrDefault(i => i.Name == taskName);
            if (task == null)
            {
                var taskBuilder = new BackgroundTaskBuilder();
                taskBuilder.Name = taskName;
                taskBuilder.TaskEntryPoint = typeof(MyRuntimeComponent.MyBackgroundTask).ToString();

                ApplicationTrigger appTrigger = new ApplicationTrigger();
                taskBuilder.SetTrigger(appTrigger);

                 task = taskBuilder.Register();

                task.Progress += Task_Progress;
                task.Completed += Task_Completed;
				
                await appTrigger.RequestAsync();

                startButton.IsEnabled = false;
                stopButton.IsEnabled = true;
            }
        }

        private void Stop_Click(object sender, RoutedEventArgs e)
        {
            Stop();
        }

        private void Task_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)
        {
            var result = ApplicationData.Current.LocalSettings.Values["factorial"];
            var progress = $"Результат: {result}";
            UpdateUI(progress);
            Stop();
        }

        private void Task_Progress(BackgroundTaskRegistration sender, BackgroundTaskProgressEventArgs args)
        {
            var progress = $"Progress: {args.Progress} %";
            UpdateUI(progress);
        }

        private async void UpdateUI(string progress)
        {
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            () =>
            {
                outputBlock.Text = progress;
            });
        }

        private async void Stop()
        {
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            () =>
            {
                var taskList = BackgroundTaskRegistration.AllTasks.Values;
                var task = taskList.FirstOrDefault(i => i.Name == taskName);
                if (task != null)
                {
                    task.Unregister(true);

                    stopButton.IsEnabled = false;
                    startButton.IsEnabled = true;
                }
            }); 
        }
    }
}

При нажатии кнопки Start вначале в локальных настройках сохраняется число 6, которое потом будет извлекаться из фоновой задачи и для которого будет вычисляться факториал:

ApplicationData.Current.LocalSettings.Values["number"] = 6;

Для запуска задачи ее надо зарегистрировать. Каждая задача представляет объект BackgroundTaskRegistration и хранится в коллекции BackgroundTaskRegistration.AllTasks. Для создания задачи и регистрации используется класс BackgroundTaskBuilder:

var taskBuilder = new BackgroundTaskBuilder();
taskBuilder.Name = taskName;
taskBuilder.TaskEntryPoint = typeof(MyRuntimeComponent.MyBackgroundTask).ToString();

ApplicationTrigger appTrigger = new ApplicationTrigger();
taskBuilder.SetTrigger(appTrigger);
task = taskBuilder.Register();

Для работы с фоновой задачи необходим триггер, ассоциированный с данной задачей. Триггер определяет, когда задача должна запускаться, и также предоставляет набор условий, необходимых для запуска задачи. Когда срабатывает триггер, система запускает класс задачи и вызывает метод, ассоциированный с данным триггером. При этом не важно, в каком состоянии находится приложение: оно активно, оно приостановлено или уже завершено системой. Без триггера, ассоциированного с фоновой задачей, эта задача никогда не сможет запуститься. Полный список доступных триггеров можно найти в msdn.

Для нашей задачи используется самый простой триггер ApplicationTrigger. С его помощью мы можем запустить задачу:

appTrigger.RequestAsync()

После этого начнут выполняться все те действия, которые предусмотрены в классе фоновой задачи.

Для задачи также определяются два обработчика событий изменения прогресса и завершения:

task.Progress += Task_Progress;
task.Completed += Task_Completed;

Событие task.Progress генерируется, когда изменяется прогресс задачи, в нашем случае это вызов в классе фоновой задачи:

taskInstance.Progress = (uint)(progress * 100 / number);

При обработке прогресса мы просто выводим его значение в текстовый блок:

task.Progress += Task_Progress;
task.Completed += Task_Completed;

При завершении задачи генерируется событие Completed, в обработчике которого отменяем регистрацию задачи:

if (task != null)
{
    task.Unregister(true);

А также получаем конечный результат.

В обработчике кнопки Stop мы также отменяем регистрацию задачи, в результате чего задача прерывается.

В результате после нажатия на кнопку Start будет запущена задача, которая подсчитает нам факториал числа 6:

Фоновые задачи в Universal Windows Platform
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850