Schnellstart: Planen von Aufgaben in einer Windows-Runtime-App mit JavaScript

Applies to Windows and Windows Phone

Die Scheduler ermöglicht Ihrer Windows-Runtime-App mit JavaScript das Ausführen von Hintergrundaufgaben, ohne die Vordergrundaufgaben der App (z. B. die Animation) zu stören. Dies kann eine langsame reagierende oder hakende Oberfläche für Benutzer weitestgehend verhindern und ggf. den Startzeitraum verkürzen. In dieser Schnellstartanleitung wird erläutert, wie Sie mit Priorität versehene Hintergrundaufgaben planen, indem Sie das Scheduler-Objekt in der Windows-Bibliothek für JavaScript verwenden.

Hinweis  Weitere Beispiele und Beispielcode zur Veranschaulichung der Scheduler-Nutzung finden Sie im Beispiel zur HTML-Planung.

Voraussetzungen

Für diese Schnellstartanleitung müssen Sie mit JavaScript eine einfache Windows-Runtime-App erstellen können, die WinJS unter Windows 8.1 oder Windows Phone 8.1 verwendet. Informationen zum Erstellen Ihrer ersten App finden Sie unter Erstellen Ihrer ersten Windows-Runtime-App mit JavaScript.

Anweisungen

Erstellen eines neues Projekts mit der Vorlage "Leere App"

In diesem Artikel wird eine einfache Vorlage Leere App in Microsoft Visual Studio 2013 verwendet. So erstellen Sie eine neue leere App:

  1. Starten Sie Microsoft Visual Studio Express 2013 für Windows.

  2. Klicken Sie auf der Registerkarte Startseite auf Neues Projekt. Das Dialogfeld Neues Projekt wird geöffnet.

  3. Erweitern Sie im Bereich Installiert die Einträge Vorlagen, JavaScript und Store-Apps. Wählen Sie den Typ von Projekt aus, den Sie erstellen möchten (Windows, Windows Phone oder Allgemein). Die verfügbaren Projektvorlagen für JavaScript werden im mittleren Bereich des Dialogfelds angezeigt.

  4. Wählen Sie im mittleren Bereich die Projektvorlage Leere App aus.

  5. Geben Sie im Textfeld Name den Namen Scheduler-Demo ein.
  6. Klicken Sie auf OK, um das Projekt zu erstellen.

Hinzufügen des HTML- und CSS-Codes für die App

Für die Beispiel-App in diesem Artikel wird eine einfache HTML-Oberfläche mit einem Raster aus zwei Zeilen und zwei Spalten verwendet. So richten Sie den HTML-Markupcode für die Seite und die Cascading Style Sheets (CSS) ein, die zum Formatieren der App verwendet werden:

  1. Öffnen Sie default.html, und fügen Sie den folgenden HTML-Code in das <body>-Element ein. Dieser Code sollte ein direktes untergeordnetes Element des <body>-Elements sein. Mit diesem HTML-Code werden drei <div>-Elemente erstellt, die zum Anzeigen der Ausgabe des JavaScript-Codes verwendet werden.

    
    <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. Öffnen Sie die Datei default.css (css/default.css), und ersetzen Sie ihren Inhalt durch den folgenden Code. Mit diesem CSS-Code wird der HTML-Code in der App in einem einfachen 2×2-Raster angeordnet.

    
    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;
    }
    
    

Hinzufügen des Codes zum Planen von Aufträgen in der Aufgabenplanung

Das Scheduler-Objekt in der Windows Library for JavaScript (WinJS) verwendet eine einzelne universelle Warteschlange mit einer auf Prioritäten basierenden Planungsrichtlinie. Dies ermöglicht Ihnen das Festlegen unterschiedlicher Prioritätsstufen für Aufgaben. Die Aufgaben werden dann gegenüber anderen Aufgaben des Systems priorisiert.

Mithilfe der Scheduler.schedule-Methode können Sie Aufträge in der Aufgabenplanung in die Warteschlange einreihen. Die schedule-Methode akzeptiert vier Parameter: work, priority, thisArg und name.

  • Der work-Parameter akzeptiert eine Funktion, mit der die auszuführenden Arbeitsschritte definiert werden. Wenn die Funktion aufgerufen wird, wird dafür ein Argument übergeben, und zwar ein IJobInfo-Objekt. Das IJobInfo-Objekt enthält Member zum Verwalten der Ausführung des Auftrags. Mit der shouldYield-Eigenschaft wird angegeben, ob der Auftrag angehalten werden soll, falls Aufgaben mit höherer Priorität anstehen. Die setWork-Methode ermöglicht das kooperative Zurückhalten des Auftrags. Er kann für den Abschluss zu einem von der Aufgabenplanung bestimmten zukünftigen Zeitpunkt neu geplant werden, ohne seine derzeitige Prioritätsstufe zu verlieren. Das IJobInfo-Objekt enthält außerdem eine job-Eigenschaft, die ein IJob-Objekt mit Details zum eigentlichen Auftrag zurückgibt.
  • Mit dem priority-Parameter wird, wie der Name schon sagt, die Priorität des Auftrags festgelegt. Er akzeptiert einen Wert von der Priority-Enumeration. Beispielsweise wird ein Auftrag mit der Priorität high vor einem Auftrag mit der Priorität normal ausgeführt, der wiederum vor einem Auftrag mit der Priorität belowNormal ausgeführt wird (usw.).
  • Sie können den thisArg-Parameter der schedule-Methode verwenden, um einen Kontext für die Ausführung des Auftrags anzugeben. Wenn der Auftrag ausgeführt wird, kann die für den work-Parameter übergebene Funktion über das this-Schlüsselwort auf den Kontext zugreifen.
  • Der vierte Parameter, name, dient zum Identifizieren des Auftrags in der Warteschlange der Planung. Mit diesem Parameter können Sie beim Debuggen oder Protokollieren von Ereignissen Aufgaben identifizieren, die in der Aufgabenplanung ausgeführt werden.

Im nächsten Verfahren erstellen Sie einen Auftrag für die Ausführung in der Aufgabenplanung. Mit diesem Code wird ein Auftrag mit niedriger Priorität geplant, bei dem die Benutzeroberfläche aktualisiert wird, während von 1 bis 100.000 gezählt wird. Eine im lexikalischen Gültigkeitsbereich des übergeordneten Elements enthaltene Zählervariable sorgt für die Beibehaltung des Auftragsstatus. Wenn ein Auftrag mit höherer Priorität in die Warteschlange gelangt, wird dieser Auftrag beendet und in der Aufgabenplanung neu eingeplant.

  1. Öffnen Sie default.js, und fügen Sie dem Handler für das app.onactivated-Ereignis den folgenden Code hinzu (nach dem Aufruf von 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. Fügen Sie den folgenden Code dem Ereignishandler für app.onactivated hinzu, und zwar unterhalb des eben hinzugefügten Codes. Mit diesem Code wird dem click-Ereignis der Schaltfläche, die im HTML-Code deklariert wird, ein Ereignishandler hinzugefügt. Der Ereignishandler plant in der Aufgabenplanung einen neuen Auftrag mit dem Namen gettingState und der Priorität normal ein. Da der counting-Auftrag die Priorität idle (Leerlauf) aufweist, hat der Auftrag gettingState Vorrang, weil dieser über die Priorität normal verfügt.

    
    // 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. Drücken Sie F5, um das Beispiel auszuführen. Klicken Sie bei laufendem Zähler dann auf die Schaltfläche Planungszustand abrufen. Die Ausgabe unter Planungszustand sieht in etwa wie folgt aus:

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

    In der Ausgabe werden die Aufträge angezeigt, die derzeit in der Warteschlange für die Aufgabenplanung enthalten sind. Mit dem Sternchen wird der Auftrag angegeben, der in der Planung gerade ausgeführt wird.

Sie können auch alle anderen Aufträge in der Planung "verdrängen", indem Sie die Scheduler.execHigh-Methode verwenden. Die execHigh-Methode führt einen Teil des Codes synchron mit der hohen Prioritätsstufe aus (wenn execHigh zurückkehrt). Damit wird sichergestellt, dass alle asynchronen Vorgänge, die während dieser Ausführung gestartet werden, eine hohe Priorität besitzen.

Mit dem folgenden Verfahren wird der gettingState-Auftrag so geändert, dass er mithilfe der execHigh-Methode geplant wird.

  1. Ersetzen Sie den click-Ereignishandler für die Schaltfläche getState durch den folgenden Code.

    
    // 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. Drücken Sie F5, um das Beispiel auszuführen. Klicken Sie bei laufendem Zähler dann auf die Schaltfläche Planungszustand abrufen. Die Ausgabe unter Planungszustand sieht nun in etwa wie folgt aus:

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

    Sie sehen, dass der Auftrag gettingState wiederum Vorrang vor dem Auftrag counting erhält. In diesem Fall wird gettingState jedoch nicht in der Warteschlange angezeigt, da die Ausführung sofort erfolgt.

Hier sehen Sie den vollständigen Code für 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();
})();


Zusammenfassung und nächste Schritte

In dieser Schnellstartanleitung wurde beschrieben, wie Sie einfache Aufträge planen und wie die Aufgabenplanung Aufträge zurückstellen kann, um Aufträgen mit höherer Priorität Vorrang einzuräumen.

Beim Durchsehen der Ausgabe des Auftrags gettingState ist Ihnen sicherlich die Zeichenfolge Drain requests aufgefallen. Die Aufgabenplanung kann alle Aufträge mit hoher Priorität aus der Warteschlange entfernen. Mit anderen Worten: Sie kann alle Aufgaben in der universellen Scheduler-Warteschlange ausführen. Bei dieser Methode tauschen Sie die schnelle Reaktion gegen hohen Durchsatz ein. Setzen Sie diese Methode mit Bedacht und nur dann ein, wenn eine gute Reaktionsfähigkeit nicht wichtig ist (z. B. beim Starten der App). Weitere Informationen finden Sie im Abschnitt zur Scheduler.requestDrain-Methode.

In dieser Schnellstartanleitung wurde nicht erläutert, wie Sie Zusagen in der Aufgabenplanung abrufen oder ausführen oder wie Sie Besitzertoken verwenden. Weitere Informationen hierzu finden Sie in den Referenzthemen zum Scheduler-Objekt.

Beispiel zur HTML-Planung

Verwandte Themen

JavaScript-Web-Worker-Beispiel

 

 

Anzeigen:
© 2014 Microsoft