Статьи

31 день Windows 8 | День № 12: Фоновые задачи

Эта статья является Днем № 12 из серии под названием «  31 день Windows 8» . Каждая из статей этой серии будет опубликована как для  HTML5 / JS, так  и для  XAML / C # . Вы можете найти дополнительные ресурсы, загрузки и исходный код на нашем  сайте .

advertisementsample

Сегодня мы говорим о фоновых задачах. Краткий способ описания фоновых задач заключается в следующем:

Фоновая задача – это код, который выполняется, когда ваше приложение этого не делает.

Подумайте о сценариях:

  • Продолжайте потоковую передачу звука, даже когда пользователь запускает другое приложение.
  • Обновите Live Tile пользователя, чтобы отразить новые данные.
  • Создайте всплывающее уведомление, чтобы пользователь знал, что произошло что-то важное.
  • Обновите экран блокировки пользователя, даже когда устройство заблокировано.

Создание фоновой задачи, созданной и зарегистрированной в системе, представляет собой двухэтапный процесс. Во-первых, вам нужно зарегистрировать фоновую задачу в вашем файле package.appxmanifest. Как только это будет сделано, вам все равно нужно зарегистрировать события этой Задачи в системе из кода вашего приложения, а затем появятся дополнительные события для управления тем, что происходит, когда завершаются Фоновые задачи. Мы рассмотрим эти сценарии в этой статье.

Моим первым шагом всегда является создание вторичного проекта, который будет содержать мои фоновые задачи. Это не обязательно, но это хорошее визуальное разделение вашего кода.

12-XAML-AddProject

При создании нового проекта выберите «Компонент среды выполнения Windows» в качестве типа проекта.

12-XAML-WindowsRuntimeComponent  По умолчанию вам предоставляется класс с именем Class1.cs. Вы можете либо переименовать его, либо просто удалить его и добавить новый класс в новый проект. В любом случае вы создадите файл класса с именем TileUpdater.cs.

Теперь фоновые задачи должны реализовывать очень специфический интерфейс:  IBackgroundTask . Он реализует только один метод, Run (), и этот метод будет вызываться, когда наше приложение запускает фоновую задачу. Чтобы начать, вот как выглядит мой C # после реализации интерфейса:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
namespace BackgroundTasks
{
    public sealed class TileUpdater : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            //We will add code here later.
        }
    }
}

Я добавил комментарий, где будет находиться наш код, но сейчас это хорошее начало.

Следующим шагом в этом процессе является объявление о том, что мы будем использовать фоновые задачи в этом приложении. Мы делаем это в файле package.appxmanifest, в разделе объявлений, как показано на снимке экрана ниже (нажмите, чтобы увеличить):

12-XAML-Appxmanifest

Как видите, мы добавили объявление для фоновых задач (вы добавите новое для каждой фоновой задачи, которую вы хотите добавить в свой проект) и установили точку входа равной BackgroundTasks.TileUpdater, нашему новому файлу класса. , Затем нам нужно зарегистрировать эту задачу в нашем реальном приложении, чтобы Windows 8 могла запускать ее в подходящее время.

Мы собираемся предпринять пару шагов в этом коде нашего файла MainPage.xaml.cs, начиная с проверки, была ли наша Фоновая задача уже зарегистрирована в системе. Я обычно делаю это, как только страница загружается, в моем методе OnNavigatedTo. Я создал новый метод CheckTaskRegistration (), который проверяет этот статус для меня и устанавливает глобальное логическое значение на странице. Конечно, вы можете сделать это и в файле App.xaml.cs, но для наших простых целей это расположение работает нормально.

bool isTaskRegistered = false;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    CheckTaskRegistration();
}
private void CheckTaskRegistration()
{
    foreach (var task in BackgroundTaskRegistration.AllTasks)
    {
        if (task.Value.Name == "TileUpdater")
        {
            isTaskRegistered = true;
            break;
        }
    }
    if (!isTaskRegistered)
    {
        RegisterBackgroundTask("TileUpdater", "BackgroundTasks.TileUpdater");
    }
}

As you can see, we are looping through the BackgroundTaskRegistration.AllTasks collection, because we could have multiple Background Tasks running under our application, and in this case, I’m only interested in the one: TileUpdater.  You can also see that I’ve made a call to RegisterBackgroundTask() if the task is not currently registered.

It is up to you how you handle this case, but in my application, I want to make sure that my Background Task is always registered, and if it has been unregistered for some reason, I want to add it back in.  Here’s what my RegisterBackgroundTask() method looks like:

private void RegisterBackgroundTask(string name, string entrypoint)
{
    BackgroundTaskBuilder btb = new BackgroundTaskBuilder();
    btb.Name = name;
    btb.TaskEntryPoint = entrypoint;
    btb.SetTrigger(new SystemTrigger(SystemTriggerType.InternetAvailable, false));
    BackgroundTaskRegistration task = btb.Register();
}

You can see that I’m passing in the name and entrypoint values, but you could certainly hard code those depending on your situation.  Since this application could have multiple Background Tasks, I decided to make this construction a little simpler and pass in some parameters.

In our registration method, we create a BackgroundTaskBuilder object, set the name and entry point, and then determine a SystemTrigger that will kick our Background Task off.  In this case, I’ve chosen the easily testable InternetAvailable trigger.  To try it, we’ll be cutting off our internet access on our machine.

If you ever have a need to unregister your Background Task, it’s pretty simple.  Here’s a sample method, UnregisterBackgroundTask() that you can use to remove the Task.

private void UnregisterBackgroundTask(string name)
{
    foreach (var task in BackgroundTaskRegistration.AllTasks)
    {
        if (task.Value.Name == name)
        {
            task.Value.Unregister(true);
        }
    }
}

In this example, we loop through the Tasks that are registered again, and if we find the one with the name we’re looking for, we call its Unregister() method, confirming with the true parameter.

So we’ve worked through registering and unregistering our Background Task, and we now have specified that our application should kick off our Background Task when the time zone of the machine changes.  Let’s write some actual code in our Background Task class, and then give this thing a test.

Earlier, we created a file named TileUpdater.cs in our new Windows Runtime Component project, and we left some space to add some code to the Run() method that must be implemented as part of the IBackgroundTask interface.  Here’s what that same file looks like with code to update our Live Tile:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
namespace BackgroundTasks
{
    public sealed class TileUpdater : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            XmlDocument tileData = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquareText04);
            XmlNodeList textData = tileData.GetElementsByTagName("text");
            textData[0].InnerText = "Background updates are absolutely amazing. #31daysofwin8";
            TileNotification notification = new TileNotification(tileData);
            notification.ExpirationTime = DateTimeOffset.UtcNow.AddSeconds(30);
            TileUpdateManager.CreateTileUpdaterForApplication().Update(notification);
        }
    }
}

Obviously, we could write a similar Background Task to implement sending a Toast notification, updating the Lock Screen, or other valuable calls to web services for example.

There’s one more thing to note about Background Tasks: they’re much harder to debug than the code in your actual application.  In fact, Microsoft has written an entire article about exactly how to Debug Your Background Tasks.  I highly recommend reading it.  They have also created a quickstart tutorial called Create and Register a Background Task.

If you would like to download the working sample code from this article, click the icon below:

downloadXAML

Tomorrow, we’re going to shift gears again, and start talking about Navigation.  Specifically, how to navigate between pages in a XAML application, and pass parameters and data as part of that process.  See you then!

downloadTheTools