После определения фоновой задачи, ее надо зарегистрировать в основном проекте, и после этого она будет готова для запуска.
Первым делом надо определить в файле манифеста приложения тип задачи. Для этого после открытия файла манифеста перейдем на вкладку Declarations. На этой вкладке в поле Available Declarations выберем пункт Background Tasks и нажмем на кнопку Add. После этого в поле Supported Declarations внизу должен быть добавлен соответствующий пункт.
В центральной части в разделе Properties определим тип задачи General, а внизу в поле Entry point впишем полное название нашего класса фоновой задачи: MyRuntimeComponent.MyBackgroundTask.
Так как у нас задача общего характера, то определяем для тип именно 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: