Практическое руководство. Управление экземпляром планировщика
Экземпляры планировщика позволяют связывать конкретные политики планирования с различными видами рабочих нагрузок. В этом разделе содержатся два базовых примера, демонстрирующих создание экземпляра планировщика и управление им.
В этих примерах создаются планировщики, использующие политики планировщика по умолчанию. Пример создания планировщика, использующего пользовательскую политику, см. в разделе Практическое руководство. Задание определенных политик планировщика.
Управление экземпляром планировщика в приложении
Создайте объект concurrency::SchedulerPolicy, содержащий значения политики, которые должны использоваться планировщиком.
Вызовите метод concurrency::CurrentScheduler::Create или concurrency::Scheduler::Create, чтобы создать экземпляр планировщика.
Если используется метод Scheduler::Create, вызовите метод concurrency::Scheduler::Attach, когда нужно связать планировщик с текущим контекстом.
Вызовите функцию CreateEvent, чтобы создать дескриптор объекта события автоматического сброса с отсутствием сигнала.
Передайте дескриптор только что созданного объекта события методу concurrency::CurrentScheduler::RegisterShutdownEvent или concurrency::Scheduler::RegisterShutdownEvent. Это позволяет зарегистрировать событие, которое необходимо настраивать при уничтожении планировщика.
Выполните задачи, которые должны планироваться текущим планировщиком.
Вызовите метод concurrency::CurrentScheduler::Detach, чтобы отключить текущий планировщик и восстановить предыдущий планировщик в качестве текущего.
Если используется метод Scheduler::Create, вызовите метод concurrency::Scheduler::Release, чтобы уменьшить число ссылок в объекте Scheduler.
Передайте дескриптор события функции WaitForSingleObject, чтобы дождаться завершения работы планировщика.
Вызовите функцию CloseHandle, чтобы закрыть дескриптор объекта события.
Пример
В следующем фрагменте кода показаны два способа управления экземпляром планировщика. В каждом примере для выполнения задачи, выводящей уникальный идентификатор текущего планировщика, сначала используется планировщик по умолчанию. Затем в каждом примере для повторного выполнения той же задачи используется экземпляр планировщика. Наконец, в каждом примере планировщик по умолчанию восстанавливается в качестве текущего и еще раз выполняет эту задачу.
В первом примере для создания экземпляра планировщика и связывания его с текущим контекстом используется класс concurrency::CurrentScheduler. Во втором примере для выполнения той же задачи используется класс concurrency::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();
}
В результате выполнения примера получается следующий результат:
Компиляция кода
Скопируйте пример кода и вставьте его в проект Visual Studio или файл с именем scheduler-instance.cpp, затем выполните в окне командной строки Visual Studio следующую команду.
cl.exe /EHsc scheduler-instance.cpp
См. также
Задачи
Практическое руководство. Задание определенных политик планировщика