Inicio rápido: programar tareas en una aplicación de Windows en tiempo de ejecución con JavaScript

Applies to Windows and Windows Phone

El Scheduler permite que tu aplicación de Windows en tiempo de ejecución con JavaScript realice trabajos en segundo plano sin interrumpir las tareas en primer plano de la aplicación (como la animación). Esto ayuda a minimizar lo que los usuarios considerarían una experiencia a "trompicones" o que parezca que no responde, y podría acortar el tiempo de inicio. En este inicio rápido se explica cómo programar las tareas en segundo plano prioritarias con el objeto Scheduler de la Biblioteca de Windows para JavaScript.

Nota  Si quieres ver más ejemplos y el código de ejemplo que describe cómo usar Scheduler, consulta la muestra de Scheduler de HTML.

Requisitos previos

En este inicio rápido debes saber crear una aplicación de Windows en tiempo de ejecución básica con JavaScript que use WinJS en Windows 8.1 o Windows Phone 8.1. Si necesitas ayuda para crear tu primera aplicación, consulta el tema sobre cómo crear tu primera aplicación de Windows en tiempo de ejecución con JavaScript.

Instrucciones

Crear un nuevo proyecto usando la plantilla Aplicación vacía

En este artículo se usa una plantilla Aplicación vacía básica en Microsoft Visual Studio 2013. Para crear una nueva Aplicación vacía, sigue estos pasos:

  1. Inicia Microsoft Visual Studio Express 2013 para Windows.

  2. En la pestaña Página de inicio, haz clic en Nuevo proyecto. Se abre el cuadro de diálogo Nuevo proyecto.

  3. En el panel Instalados, expande Plantillas, JavaScript y luego Aplicaciones de la Tienda. Selecciona el tipo de proyecto (Windows, Windows Phone, o Universal) que quieras crear. Las plantillas de proyecto instaladas para JavaScript se muestran en panel central del cuadro de diálogo.

  4. En el panel central, selecciona la plantilla de proyecto Aplicación vacía.

  5. En el cuadro de texto Nombre, escribe Scheduler demo.
  6. Haz clic en Aceptar para crear el proyecto.

Agregar el HTML y CSS de la aplicación

La aplicación de muestra de este artículo usa una interfaz HTML muy sencilla dispuesta en una cuadrícula con dos filas y dos columnas. Para establecer el marcado HTML de la página y las (CSS) que se usan para crear el estilo de la aplicación, haz lo siguiente:

  1. Abre default.html e inserta el siguiente HTML en el elemento <body>. Este código debería ser un elemento secundario directo del elemento <body>. El HTML crea tres elemento <div> que se usan para mostrar la salida del código JavaScript.

    
    <div id="scheduler">
        <button id="getState">Get scheduler state</button><br />
    </div>
    <div id="counter">
        <h2>Counter</h2>
        <div id="counterOutput"></div>
    </div>
    <div id="state">
        <h2>Scheduler state</h2>
        <textarea id="stateResult"></textarea>
    </div>
    
    
  2. Abre el archivo default.css (css/default.css) y reemplaza el contenido por el siguiente código. Esta CSS organiza el HTML de la aplicación en una sencilla cuadrícula de 2 × 2.

    
    body {
        display: -ms-grid;
        -ms-grid-columns: 500px 1fr;
        -ms-grid-rows: 500px 1fr
    }
    body * {
        margin: 20px;
    }
    
    #scheduler {
        -ms-grid-column: 1;
        -ms-grid-row: 1
    }
    
    #state {
        -ms-grid-column: 2;
        -ms-grid-row: 2;
    }
    
    #state textarea {
        width: 400px;
        height: 200px;
    }
    
    #counter {
        -ms-grid-column: 1;
        -ms-grid-row: 2;
    }
    
    #counter div {
        font-size: 20pt;
        color: aqua;
    }
    
    

Agregar código para programar trabajos en el programador

El objeto Scheduler en la Biblioteca de Windows para JavaScript (WinJS) usa una única cola universal con una directiva de programación basada en prioridades. Esto te permite especificar tareas en varios niveles de prioridad. Las tareas después se priorizan con otras tareas dentro del sistema.

Los trabajos se pueden poner en cola en el programador mediante el método Scheduler.schedule. El método schedule acepta cuatro parámetros work, priority, thisArg y name.

  • El parámetro work acepta una función que define el trabajo que se debe efectuar. Cuando se llama a la función, pasa a un único argumento: un objeto IJobInfo. Este objeto IJobInfo incluye los miembros necesarios para administrar la ejecución del trabajo. La propiedad shouldYield indica si el trabajo se debe pausar en favor de otros trabajos con mayor prioridad. El método setWork permite que el trabajo se produzca cooperativamente. Puede reprogramarse para terminar su trabajo en el futuro cuando el programador determine que es el momento adecuado, sin que el trabajo pierda su puesto en su nivel de prioridad actual. El objeto IJobInfo también incluye una propiedad job que devuelve un objeto IJob, que contiene los detalles del propio trabajo.
  • El parámetro priority establece la prioridad del trabajo. Acepta un valor de la enumeración Priority. Por ejemplo, se ejecuta un trabajo de prioridad high antes que un trabajo de prioridad normal, que se ejecuta antes que un trabajo de prioridad belowNormal (y así sucesivamente).
  • Puedes usar el parámetro thisArg del método schedule para especificar un contexto en el que ejecutar el trabajo. Cuando se ejecuta el trabajo, la función que se pasó en el parámetro work puede acceder al contexto mediante la palabra clave this.
  • El cuarto parámetro, name, proporciona un modo de identificar el trabajo dentro de la cola del programador. Este parámetro permite identificar las tareas que se están ejecutando en el programador al depurar o registrar eventos.

En este siguiente procedimiento, crearán un trabajo para que se ejecute en el programador. Este código programa un trabajo de baja prioridad que cuenta de uno a 100.000, y actualiza la interfaz de usuario a medida que la cuenta avanza. Una variable de contador, que se incluye en el ámbito léxico del elemento principal, mantiene el estado del trabajo. Cuando un trabajo con mayor prioridad se incorpora a la cola, este trabajo se cierra y reprograma su tarea en el programador.

  1. Abre default.js y agrega el siguiente código al controlador del evento app.onactivated (después de la llamada a args.setPromise).

    
    
    var scheduler = WinJS.Utilities.Scheduler;
    
    // Define a low-priority, time-consuming, job for the scheduler
    // to execute. This job counts from 1 to 100K, displaying each
    // number that it counts.
    var counter = 0;
    var counting = function (jobInfo) {
    
        while (counter < Math.pow(10, 5)) {
    
            counter++;
            counterOutput.innerText = counter;
    
            // Force the job to pause if a higher priority job
            // comes into the queue, and resume the job after
            // the other job is complete. Note that you need to 
            // include the 'break' to exit the while block.
            if (jobInfo.shouldYield) {
                jobInfo.setWork(counting);
                break;
            }    
        }
    }
    
    // Schedule the counting job at a low-level priority.
    scheduler.schedule(counting, 
        scheduler.Priority.idle, 
        null,
        "counting")
    
    
  2. Agrega el siguiente código al controlador de eventos de app.onactivated, debajo del código que has agregado antes. Este código agrega un controlador de eventos al evento click del botón declarado en el HTML. El controlador de eventos programa un nuevo trabajo llamado gettingState en el programador con una prioridad normal. Como el trabajo counting tiene una prioridad de idle, el trabajo gettingState se adelanta a él porque tiene una prioridad normal.

    
    // Get the state of the scheduler. While the counting job
    // is running, this will display two jobs: this 'getting state'
    // job and the 'counting' job.
    var gettingState = function (jobInfo) {
        var currentTime = new Date();
        currentTime = currentTime.toLocaleTimeString();
    
        var state = scheduler.retrieveState();
        stateResult.value = currentTime + "\n\n" + state;
    }
    
    // When the button is clicked, display the current state of 
    // the scheduler to the user. This is scheduled as a 
    // normal-priority job so that the 'counting' job will yield to it.
    getState.addEventListener("click", function () { 
    
        scheduler.schedule( 
            gettingState, 
            scheduler.Priority.normal, 
            null, 
            "getting state");
                    
    });
    
    
  3. Presiona F5 para ejecutar la muestra y, con el contador en marcha, haz clic en el botón Get scheduler state. La salida de Scheduler state tiene este aspecto.

    9:11:52PM
    
    Jobs:
      *id: 3, priority: normal, name: getting state
       id: 2, priority: idle, name: counting
    Drain requests:
       None
    

    El resultado refleja los trabajos que hay actualmente en cola en el programador. El asterisco señala el trabajo que se está ejecutando en ese momento en el programador.

También puedes adelantar todos los demás trabajos en el programador mediante el método Scheduler.execHigh. El método execHigh ejecuta algo de código de forma sincrónica (se produce cuando vuelve execHigh) en el nivel de prioridad alto. Esto garantiza que las operaciones asincrónicas que se inicien durante dicha ejecución tengan una prioridad alta.

El siguiente procedimiento cambia el trabajo gettingState parta que se programe con el método execHigh.

  1. Reemplaza el controlador de eventos clickdel botón getState por el siguiente código.

    
    // When the button is clicked, display the current state of 
    // the scheduler to the user. This is scheduled with the highest
    // priority, so the counting job yields to it.
    getState.addEventListener("click", function () {
    
        scheduler.execHigh(gettingState);
    
    });
    
    
  2. Presiona F5 para ejecutar un ejemplo y, con el contador en marcha, haz clic en el botón Get scheduler state. La salida de Scheduler state ahora tiene este aspecto.

    9:32:49PM
    
    Jobs:
       id: 2, priority: idle, name: counting
    Drain requests:
       None
    

    Verás que el trabajo gettingState vuelve a adelantarse al trabajo counting. Sin embargo, en este caso gettingState no se muestra en la cola porque se ejecuta inmediatamente.

Este es el código completo de default.js.



(function () {
    "use strict";

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;
    var scheduler = WinJS.Utilities.Scheduler;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll());

            // Define a low-priority, time-consuming, job for the scheduler
            // to execute. This job counts from 1 to 100K, displaying each
            // number that it counts.
            var counter = 0;
            var counting = function (jobInfo) {

                while (counter < Math.pow(10, 5)) {

                    counter++;
                    counterOutput.innerText = counter;

                    // Force the job to pause if a higher priority job
                    // comes into the queue, and resume the job after
                    // the other job is complete. Note that you need to 
                    // include the 'break' to exit the while block.
                    if (jobInfo.shouldYield) {
                        jobInfo.setWork(counting);
                        break;
                    }    
                }
            }

            // Schedule the counting job at a low-level priority.
            scheduler.schedule(counting, 
                scheduler.Priority.idle, 
                null,
                "counting")

            // Get the state of the scheduler. While the counting job
            // is running, this will display two jobs: this 'getting state'
            // job and the 'counting' job.
            var gettingState = function (jobInfo) {
                var currentTime = new Date();
                currentTime = currentTime.toLocaleTimeString();

                var state = scheduler.retrieveState();
                stateResult.value = currentTime + "\n\n" + state;
            }

            // When the button is clicked, display the current state of 
            // the scheduler to the user. This is scheduled as a 
            // normal-priority job so that the 'counting' job will yield to it.
            getState.addEventListener("click", function () {

                // Uncomment the following line of code to run the gettingState
										    		// job at a 'normal' priority.
                //scheduler.schedule(gettingState,scheduler.Priority.normal, null, "getting state");
                scheduler.execHigh(gettingState);

            });
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    app.start();
})();


Resumen y pasos siguientes

En este inicio rápido has aprendido a programar trabajos sencillos y el modo en que el programador puede adelantar trabajos para favorecer los de mayor prioridad.

Cuando viste la salida del trabajo gettingState, es probable que te fijaras en la cadena Drain requests. El programador puede consumir todos los trabajos de alta prioridad de la cola; es decir, puede ejecutar todas las tareas de la cola universal para el Scheduler. Con este método, se cambia la capacidad de respuesta por el rendimiento. Es método es mejor usarlo solo de vez en cuando y cuando la capacidad de respuesta no sea un problema (por ejemplo, durante el inicio de la aplicación). Para más información, consulta el método Scheduler.requestDrain.

En este inicio rápido tampoco hemos abordado cómo obtener o ejecutar promesas en el programador o cómo usar tokens de propietario. Para obtener más información sobre estos temas, consulta el tema de referencia de objetos Scheduler.

Muestra de Scheduler de HTML

Temas relacionados

Muestra de Web Workers de JavaScript

 

 

Mostrar:
© 2014 Microsoft