Статьи

Планировщик WinJS

Windows 8.1 поставляется с новой функцией в WinJS SDK: планировщик. Посмотрим что это такое и как им пользоваться!

В Windows 8 каждая работа почти выполняется, как только вы ее выполняете. Вы можете поиграть с  функцией msSetImmediate,  но это все еще был небольшой режим «взломать», чем «код».

В Windows 8.1 SDK представляет планировщик, используемый всей средой WinJS.  Этот планировщик помогает вам определить, что важно (анимация, визуальная обратная связь, управление вводом пользователя) из того, что может быть отложено (фоновая работа, обработка данных не используется сразу).

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

Что в нем ?

Все живет в пространстве имен  WinJS.Utilities.Scheduler и написано в javascript.
Это пространство имен часто называют «Планировщик» или «S» в примерах Microsoft.

var S = WinJS.Utilities.Scheduler;

Необходимо знать 4 важных объекта:

  • WinJS.Utilities.Scheduler : основное пространство имен со множеством статических функций, которое позволяет запускать и управлять заданиями
  • WinJS.Utilities.Scheduler.IJob  : все это работа. Когда вы запускаете задачу / работу с помощью планировщика, он возвращает вам объект IJob, для которого вы можете вызывать методы управления.
  • WinJS.Utilities.Scheduler.IJobInfo  : информация, передаваемая вашей рабочей функции при выполнении.
  • WinJS.Utilities.Scheduler.IOwnerToken  : вы хотите быть владельцем задачи и управлять группой заданий, а затем использовать это.

Как это использовать (101)?

Запуск работы так же прост, как и предоставление функции:

var job = WinJS.Utilities.Scheduler.schedule(function willBeExecuted(){
 
//work to be done
});

Есть также некоторые необязательные параметры, которые также могут быть установлены: приоритет (по умолчанию WinJS.Utilities.Scheduler.Priority.normal.), Этот параметр, который будет установлен при выполнении функции и имя (полезно при отладке):

var whoAmI = {};
var job =  WinJS.Utilities.Scheduler.schedule(function willBeExecuted(){
 
//work to be done
} , WinJS.Utilities.Scheduler.Priority.normal, whoAmI, " I am the job name" );

Возвращенный объект является объектом IJob, и вы можете вызвать на нем некоторую функцию, чтобы отменить планирование, приостановить его, возобновить и получить некоторую информацию, такую ​​как имя, приоритет, владелец и т. Д.

//create a job
var job =  WinJS.Utilities.Scheduler.schedule( /* ...*/);
//pause the job
job.pause();
 
//resume it in 5 secs
WinJS.Promise.timeout(5000).then(job.resume);
 
//reads the name of the job 
var name = job.name;

IJobInfo и уступает

В этом случае «уступать» означает «позволить другим задачам, более важным, чем я, начать и выполнять свою работу, пока я выполняю и приостанавливаю меня».
Предположим, у вас есть задание, которое занимает 10 секунд, и вы можете разделить его на 10 частей.
Затем вы можете запустить задание с помощью планировщика, выполнить первую часть и сказать ему: сделать что-то еще (другие задания с более высоким приоритетом), если необходимо, затем перезвоните мне. Планировщик будет управлять этим  процессом  для вас.

Когда ваша работа выполняется, параметр фактически предоставляется, и он реализует  интерфейс IJobInfo . Этот объект jobInfo имеет 2 важные функции и 1 важное поле:

  • setPromise : вызов его с предоставлением функции указывает планировщику дождаться этого обещания, прежде чем перезвонить вам. Если вам необходимо локально загрузить интернет-ресурс, планировщику не нужно звонить вам раньше, и вы можете задать обещание дождаться завершения загрузки.
  • setWork:  вызов ее с предоставлением функции сообщает планировщику, какую функцию вызывать, когда он хочет продолжить обработку (после выполнения более важных задач).
  • shouldYield  : прочитайте это, чтобы узнать, должна ли функция давать результат: если true, вы устанавливаете следующую функцию для вызова, используя функцию setWork, и вы возвращаетесь. Если ложно, вы делаете свою работу.

Итак, как мы реализуем эту функцию? Создавая функцию обработки, которая будет обрабатывать каждую часть в цикле. На каждом цикле мы будем проверять, нужно ли нам уступать. Если это так, мы говорим планировщику перезвонить нам, когда он хочет перезапустить наш процесс. Если процесс завершен (обработано 10 частей), мы просто возвращаемся.

Вот как я буду реализовывать эту «обработку 10 частей».

var partProcessed = 0;
 
function executeYieldingTask() {
     
    // schedule some work
    S.schedule(function myScheduledJob(jobInfo) {
 
        //Process the 10 parts
        while (partProcessed < 10) {
 
 
            //check if I have to yield :new job with higher priority
            // may have been scheduled
            if (jobInfo.shouldYield) {
 
                //tells the Scheduler to execute myScheduledJob
                // when it's done executing higher priority task 
                jobInfo.setWork(myScheduledJob);
 
                //we yield so we exit the 'process loop'
                break;
 
            }
            else {
                /* process the part partProcessed */
                partProcessed = partProcessed + 1;
            }
        }
    }, S.Priority.idle);
}

Интерфейс IOwnerToken и как его использовать

IOwnerToken — это интерфейс, который представляет владельца задания. Под владельцем это означает «хозяин»: тот, кто контролирует и управляет им.
Токен может быть настроен на несколько заданий одновременно, и в этом интерфейсе есть одна функция: cancelAll. Эта функция просто отменяет все задания, принадлежащие токену.

Чтобы создать токен, вы должны вызвать функцию createOwnerToken. Затем вы можете назначить его на созданную работу.

//create a token
var ownerToken = WinJS.Utilities.Scheduler.createOwnerToken();
 
//create jobs
var job1 =  WinJS.Utilities.Scheduler.schedule( /* ...*/);
var job2 =  WinJS.Utilities.Scheduler.schedule( /* ...*/);
 
//Be in control
job1.owner = ownerToken ;
job2.owner = ownerToken ;
 
//Cancel the jobs at once :
ownerToken.cancelAll();

Этот токен действительно полезен, когда вы хотите управлять группой заданий одновременно.  Создание владельца, если пользователь делает что-то еще, переходит на другую страницу: вы отменяете все задачи одновременно и получаете некоторое количество процессорного сока.

Некоторые полезные функции

Теперь давайте обнаружим некоторые полезные функции при игре с заданиями и планировщиком.

  • requestDrain  : используйте эту функцию, если вы хотите быть уверены, что все запланированные задания с заданным приоритетом завершены. Просто передайте целевой приоритет, он возвращает обещание, которое можно использовать, чтобы узнать о завершении «состояния ошибки» при обработке очереди
  • retrieveState  : вам нужно сбросить очередь расписания для  отладки  ? Используйте эту функцию  :) . Выдает имя, идентификатор, приоритет задач и т. Д.
  • schedulePromiseXXX  : существует множество функций с похожими именами (schedulePromiseAboveNormal и т. д.). Эти функции принимают обещание в качестве параметра. Это гарантирует, что обработчик завершения / ошибки обрабатывается в планировщике с заданным приоритетом. Если вы хотите, чтобы тоб обработчика завершения обрабатывался, как только обещание выполнено, используйте schedulePromiseHigh.

Вот пример кода:

//requestDrain example
var drainPromise = WinJS.Utilities.Scheduler.requestDrain(priority, name);
 
drainPromise.done( 
      function complete(){console.log("queue drained");},
      function error(){ });
 
//retrieveState example :  
var S= WinJS.Utilities.Scheduler;
S.schedule(function () {/* */ }, S.Priority.aboveNormal,null,"a task name");
S.schedule(function () {/* */ }, S.Priority.idle,null, "infinite square name");
S.schedule(function () {/* */ }, S.Priority.belowNormal,null,"another task name");
  
var state = WinJS.Utilities.Scheduler.retrieveState();
/*
  state looks like this :
  Jobs:
     id: 22, priority: aboveNormal, name: a task name
     id: 24, priority: belowNormal, name: another task name
     id: 23, priority: idle, name: infinite square name
    Drain requests:
     None
*/
 
//schedulePromiseXXX example
var dldPromise = WinJS.xhr({url:'www.infiniteSquare.com'});
WinJS.Utilities.Scheduler.schedulePromiseHigh(dldPromise)
     .then(function(xhrResult){
     /* process interesting content */
      });