Практическое руководство. Управление экземпляром планировщика

Экземпляры планировщика позволяют связать определенные политики планирования с различными типами рабочих нагрузок. В этом разделе содержатся два основных примера, в котором показано, как создавать экземпляр планировщика и управлять ими.

В примерах создаются планировщики, использующие политики планировщика по умолчанию. Пример создания планировщика, использующего настраиваемую политику, см. в разделе "Практическое руководство. Указание конкретных политик планировщика".

Управление экземпляром планировщика в приложении

  1. Создайте объект параллелизма::SchedulerPolicy, содержащий значения политики для используемого планировщика.

  2. Вызовите метод параллелизма::CurrentScheduler::Create или метод параллелизма::Scheduler::Create для создания экземпляра планировщика.

    При использовании Scheduler::Create метода вызовите метод параллелизма::Scheduler::Attach , если необходимо связать планировщика с текущим контекстом.

  3. Вызовите функцию CreateEvent, чтобы создать дескриптор для объекта события без сигнала, автоматического сброса.

  4. Передайте дескриптор объекту события, созданному только что созданному методу параллелизма::CurrentScheduler::RegisterShutdownEvent или методу concurrency::Scheduler::RegisterShutdownEvent. Это регистрирует событие, которое необходимо задать при уничтожении планировщика.

  5. Выполните задачи, которые нужно запланировать текущим планировщиком.

  6. Вызовите метод параллелизма::CurrentScheduler::D etach, чтобы отключить текущий планировщик и восстановить предыдущий планировщик в качестве текущего.

    При использовании Scheduler::Create метода вызовите метод параллелизма::Scheduler::Release для уменьшения количества Scheduler ссылок объекта.

  7. Передайте дескриптор событию в функцию WaitForSingleObject , чтобы дождаться завершения работы планировщика.

  8. Вызовите функцию CloseHandle, чтобы закрыть дескриптор к объекту события.

Пример

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

В первом примере используется класс параллелизма::CurrentScheduler для создания экземпляра планировщика и связывания его с текущим контекстом. Второй пример использует класс параллелизма::Scheduler для выполнения той же задачи. Как правило, CurrentScheduler класс используется для работы с текущим планировщиком. Второй пример, использующий Scheduler класс, полезен, если вы хотите контролировать, когда планировщик связан с текущим контекстом или когда требуется связать определенные планировщики с определенными задачами.

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

using namespace concurrency;
using namespace std;

// Prints the identifier of the current scheduler to the console.
void perform_task()
{
   // A task group.
   task_group tasks;

   // Run a task in the group. The current scheduler schedules the task.
   tasks.run_and_wait([] { 
      wcout << L"Current scheduler id: " << CurrentScheduler::Id() << endl;
   });
}

// Uses the CurrentScheduler class to manage a scheduler instance.
void current_scheduler()
{
   // Run the task.
   // This prints the identifier of the default scheduler.
   perform_task();

   // For demonstration, create a scheduler object that uses 
   // the default policy values.
   wcout << L"Creating and attaching scheduler..." << endl;
   CurrentScheduler::Create(SchedulerPolicy());

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

   // Run the task again.
   // This prints the identifier of the new scheduler.
   perform_task();

   // Detach the current scheduler. This restores the previous scheduler
   // as the current one.
   wcout << L"Detaching scheduler..." << endl;
   CurrentScheduler::Detach();

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

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

   // Run the sample task again.
   // This prints the identifier of the default scheduler.
   perform_task();
}

// Uses the Scheduler class to manage a scheduler instance.
void explicit_scheduler()
{
   // Run the task.
   // This prints the identifier of the default scheduler.
   perform_task();

   // For demonstration, create a scheduler object that uses 
   // the default policy values.
   wcout << L"Creating scheduler..." << endl;
   Scheduler* scheduler = Scheduler::Create(SchedulerPolicy());

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

   // Associate the scheduler with the current thread.
   wcout << L"Attaching scheduler..." << endl;
   scheduler->Attach();

   // Run the sample task again.
   // This prints the identifier of the new scheduler.
   perform_task();

   // Detach the current scheduler. This restores the previous scheduler
   // as the current one.
   wcout << L"Detaching scheduler..." << endl;
   CurrentScheduler::Detach();

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

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

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

   // Run the sample task again.
   // This prints the identifier of the default scheduler.
   perform_task();
}

int wmain()
{
   // Use the CurrentScheduler class to manage a scheduler instance.
   wcout << L"Using CurrentScheduler class..." << endl << endl;
   current_scheduler();

   wcout << endl << endl;

   // Use the Scheduler class to manage a scheduler instance.
   wcout << L"Using Scheduler class..." << endl << endl;
   explicit_scheduler();
}

В этом примере формируются следующие данные:

Using CurrentScheduler class...

Current scheduler id: 0
Creating and attaching scheduler...
Current scheduler id: 1
Detaching scheduler...
Current scheduler id: 0

Using Scheduler class...

Current scheduler id: 0
Creating scheduler...
Attaching scheduler...
Current scheduler id: 2
Detaching scheduler...
Current scheduler id: 0

Компиляция кода

Скопируйте пример кода и вставьте его в проект Visual Studio или вставьте его в файл с именем scheduler-instance.cpp , а затем выполните следующую команду в окне командной строки Visual Studio.

cl.exe /EHsc scheduler-instance.cpp

См. также

Экземпляры планировщика
Практическое руководство. Задание определенных политик планировщика