Gewusst wie: Angeben von bestimmten Planerrichtlinien

Mithilfe von Planerrichtlinien können Sie die Strategie festlegen, die der Planer zum Verwalten von Aufgaben verwendet. In diesem Thema wird veranschaulicht, wie eine Planerrichtlinie verwendet wird, um die Threadpriorität einer Aufgabe zu erhöhen, die eine Statusanzeige an die Konsole ausgibt.

Ein Beispiel, das benutzerdefinierte Zeitplanrichtlinien zusammen mit asynchronen Agents verwendet, finden Sie unter How to: Create Agents that Use Specific Scheduler Policies.

Beispiel

Im folgenden Beispiel werden zwei Aufgaben parallel ausgeführt. Der erste Vorgang berechnet die n-fibonacci-Zahl. Die zweite Aufgabe gibt eine Statusanzeige an die Konsole aus.

Die erste Aufgabe verwendet die rekursive Zerlegung zur Berechnung der Fibonacci-Zahl. Das heißt, jede Aufgabe erstellt rekursiv Unteraufgaben zur Berechnung des Gesamtergebnisses. Es kann vorkommen, dass eine Aufgabe, die rekursive Zerlegung verwendet, alle verfügbaren Ressourcen belegt, die anderen Aufgaben dann fehlen. In diesem Beispiel kann die Aufgabe zur Ausgabe der Statusanzeige möglicherweise nicht rechtzeitig auf Computerressourcen zugreifen.

Um die Aufgabe bereitzustellen, die einen fairen Zugriff auf Computerressourcen druckt, werden in diesem Beispiel Schritte verwendet, die unter "How to: Manage a Scheduler Instance " beschrieben werden, um eine Schedulerinstanz mit einer benutzerdefinierten Richtlinie zu erstellen. Die benutzerdefinierte Richtlinie gibt die Threadpriorität für die höchste Prioritätsklasse an.

In diesem Beispiel werden die Klassen "concurrency::call " und "concurrency::timer " verwendet, um die Statusanzeige zu drucken. Diese Klassen verfügen über Versionen ihrer Konstruktoren, die einen Verweis auf ein Parallelitätsobjekt::Scheduler verwenden, das sie plant. In unserem Beispiel wird der Standardplaner zur Planung der Aufgabe verwendet, die die Fibonacci-Zahl berechnet, und die Planerinstanz wird zur Planung der Aufgabe verwendet, die die Statusanzeige ausgibt.

Um die Vorteile der Verwendung eines Planers mit einer benutzerdefinierten Richtlinie aufzuzeigen, wird in diesem Beispiel die gesamte Aufgabe zweimal ausgeführt. Dabei werden im Beispiel zunächst beide Aufgaben mithilfe des Standardplaners geplant. Beim zweiten Durchlauf wird die erste Aufgabe mithilfe des Standardplaners und die zweite Aufgabe mithilfe eines Planers mit einer benutzerdefinierten Richtlinie geplant.

// scheduler-policy.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
   if (n < 2)
      return n;

   // Compute the components in parallel.
   int n1, n2;
   parallel_invoke(
      [n,&n1] { n1 = fibonacci(n-1); },
      [n,&n2] { n2 = fibonacci(n-2); }
   );
  
   return n1 + n2;
}

// Prints a progress indicator while computing the nth Fibonacci number.
void fibonacci_with_progress(Scheduler& progress_scheduler, int n)
{
   // Use a task group to compute the Fibonacci number.
   // The tasks in this group are scheduled by the current scheduler.
   structured_task_group tasks;

   auto task = make_task([n] {
      fibonacci(n);
   });
   tasks.run(task);

   // Create a call object that prints its input to the console.
   // This example uses the provided scheduler to schedule the 
   // task that the call object performs.
   call<wchar_t> c(progress_scheduler, [](wchar_t c) { 
      wcout << c; 
   });

   // Connect the call object to a timer object. The timer object
   // sends a progress message to the call object every 100 ms.
   // This example also uses the provided scheduler to schedule the 
   // task that the timer object performs.
   timer<wchar_t> t(progress_scheduler, 100, L'.', &c, true);
   t.start();

   // Wait for the task that computes the Fibonacci number to finish.
   tasks.wait();

   // Stop the timer.
   t.stop();

   wcout << L"done" << endl;
}

int wmain()
{  
   // Calculate the 38th Fibonacci number.
   const int n = 38;

   // Use the default scheduler to schedule the progress indicator while 
   // the Fibonacci number is calculated in the background.

   wcout << L"Default scheduler:" << endl;
   fibonacci_with_progress(*CurrentScheduler::Get(), n);

   // Now use a scheduler that has a custom policy for the progress indicator.
   // The custom policy specifies the thread priority to the highest 
   // priority class.
   
   SchedulerPolicy policy(1, ContextPriority, THREAD_PRIORITY_HIGHEST);
   Scheduler* scheduler = Scheduler::Create(policy);

   // Register to be notified when the scheduler shuts down.
   HANDLE hShutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
   scheduler->RegisterShutdownEvent(hShutdownEvent);

   wcout << L"Scheduler that has a custom policy:" << endl;
   fibonacci_with_progress(*scheduler, n);

   // Release the final reference to the scheduler. This causes the scheduler
   // to shut down.
   scheduler->Release();

   // Wait for the scheduler to shut down and destroy itself.
   WaitForSingleObject(hShutdownEvent, INFINITE);

   // Close the event handle.
   CloseHandle(hShutdownEvent);
}

Folgende Ergebnisse werden zurückgegeben:

Default scheduler:
...........................................................................done
Scheduler that has a custom policy:
...........................................................................done

Obwohl beide Durchläufe zum gleichen Ergebnis führen, ermöglicht die Version mit der benutzerdefinierten Richtlinie die Ausführung der Aufgabe zur Ausgabe der Statusanzeige mit erhöhter Priorität, das heißt mit höherer Reaktionsgeschwindigkeit.

Kompilieren des Codes

Kopieren Sie den Beispielcode, fügen Sie ihn in ein Visual Studio-Projekt ein, oder fügen Sie ihn in eine Datei ein, die benannt scheduler-policy.cpp ist, und führen Sie dann den folgenden Befehl in einem Visual Studio-Eingabeaufforderungsfenster aus.

cl.exe /EHsc scheduler-policy.cpp

Siehe auch

Planerrichtlinien
Vorgehensweise: Verwalten einer Planerinstanz
Vorgehensweise: Erstellen von Agents, die bestimmte Planerrichtlinien verwenden