Udostępnij za pośrednictwem


Porady: określanie specjalnych zasad harmonogramu

Zasady harmonogramu umożliwiają kontrolowanie strategii używanej przez harmonogram podczas zarządzania zadaniami. W tym temacie pokazano, jak za pomocą zasad harmonogramu zwiększyć priorytet wątku zadania, które wyświetla wskaźnik postępu w konsoli.

Przykład użycia niestandardowych zasad harmonogramu razem z agentami asynchronicznymi znajduje się w temacie How to: Create Agents that Use Specific Scheduler Policies (Jak utworzyć agentów korzystających z określonych zasad harmonogramu).

Przykład

Poniższy przykład wykonuje dwa zadania równolegle. Pierwsze zadanie oblicza n numerFibonacciego . Drugie zadanie wyświetla wskaźnik postępu w konsoli.

Pierwsze zadanie używa rekursywnej dekompozycji do obliczenia liczby Fibonacciego. Oznacza to, że każde zadanie cyklicznie tworzy podzadania w celu obliczenia ogólnego wyniku. Zadanie korzystające z dekompozycji cyklicznego może używać wszystkich dostępnych zasobów, a tym samym zagłodzać inne zadania. W tym przykładzie zadanie, które wyświetla wskaźnik postępu, może nie otrzymać czasu dostępu do zasobów obliczeniowych.

Aby udostępnić zadanie, które wyświetla komunikat o postępie sprawiedliwego dostępu do zasobów obliczeniowych, w tym przykładzie użyto kroków opisanych w temacie How to: Manage a Scheduler Instance to create a scheduler instance that has a custom policy (Jak zarządzać wystąpieniem harmonogramu w celu utworzenia wystąpienia harmonogramu z zasadami niestandardowymi). Zasady niestandardowe określają priorytet wątku jako klasę o najwyższym priorytcie.

W tym przykładzie użyto klas concurrency::call i concurrency::timer w celu wydrukowania wskaźnika postępu. Te klasy mają wersje swoich konstruktorów, które przyjmują odwołanie do obiektu współbieżności::Scheduler , który je planuje. W przykładzie użyto domyślnego harmonogramu, aby zaplanować zadanie, które oblicza liczbę Fibonacciego i wystąpienie harmonogramu, aby zaplanować zadanie, które wyświetla wskaźnik postępu.

Aby zilustrować korzyści wynikające z używania harmonogramu z zasadami niestandardowymi, ten przykład wykonuje zadanie ogólne dwa razy. W przykładzie użyto domyślnego harmonogramu, aby zaplanować oba zadania. W tym przykładzie użyto domyślnego harmonogramu, aby zaplanować pierwsze zadanie, oraz harmonogram, który ma niestandardowe zasady, aby zaplanować drugie zadanie.

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

W tym przykładzie są generowane następujące dane wyjściowe.

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

Mimo że oba zestawy zadań generują ten sam wynik, wersja, która używa zasad niestandardowych, umożliwia zadanie, które wyświetla wskaźnik postępu w celu uruchomienia z podwyższonym priorytetem, tak aby zachowywał się szybciej.

Kompilowanie kodu

Skopiuj przykładowy kod i wklej go w projekcie programu Visual Studio lub wklej go w pliku o nazwie scheduler-policy.cpp , a następnie uruchom następujące polecenie w oknie wiersza polecenia programu Visual Studio.

cl.exe /EHsc scheduler-policy.cpp

Zobacz też

Zasady harmonogramu
Instrukcje: zarządzanie wystąpieniem harmonogramu
Instrukcje: tworzenie agentów korzystających ze specjalnych zasad harmonogramu