Потоки в Windows. Приостановка и возобновление потоков/процессов. Функция Sleep.

Для Windows механизм распределения процессорного времени между потоками примерно следующий. Поток выполняет код и манипулирует данными в адресном пространстве своего процесса примерно 20 мкс. Далее Windows сохраняет значения регистров процессора в контексте потока и приостанавливает его выполнение. Система просматривает остальные объекты ядра «поток», подлежащие выполнению и выбирает один из них, загружает его контекст в регистры процессора, и все повторяется. Этот цикл операций – выбор потока, загрузка его контекста, выполнение и сохранение контекста – начинается с момента запуска системы и продолжается до её выключения. Windows потому и называется системой с вытесняющей многозадачностью, что в любой момент может приостановить любой поток и вместо него запустить другой. Однако этим механизмом можно управлять, хотя и очень ограниченно.

Приостановка и возобновление потоков. В объекте ядра «поток» имеется переменная – счетчик числа простоев данного потока. При вызове CreateProcess или CreateThread он инициализируется значением, равным 1, которое запрещает системе выделять новому потоку процессорное время. Сразу после создания поток не готов к выполнению, ему нужно время для инициализации.

После того, как поток полностью инициализирован, CreateProcess или CreateThread проверяет, не передан ли ей флаг CREATE_SUSPENDED, и, если да, возвращает управление, оставив поток в приостановленном состоянии. В ином случае счетчик простоев обнуляется, и поток включается в число планируемых – если только он не ждет какого-либо события.

Создав поток в приостановленном состоянии, можно настроить некоторые его свойства (например, приоритет, о котором мы поговорим позже). Закончив настройку, необходимо разрешить выполнение потока. Для этого используется функция ResumeThread:

DWORD ResumeThread(HANDLE hThread);

Если вызов ResumeThread прошел успешно, она возвращает предыдущее значение счетчика простоев данного потока; в ином случае – 0xFFFFFFFF.

Выполнение отдельного потока можно приостанавливать несколько раз. Если поток приостановлен 3 раза, то и возобновлен он должен быть тоже 3 раза – лишь тогда система выделит ему процессорное время. Выполнение потока можно приостановить не только при его создании с флагом CREATE_SUSPENDED, но и вызовом SuspendThread:

DWORD SuspendThread(HANDLE hThread);

Любой поток может вызвать эту функцию и приостановить выполнение другого потока.

Приостановка и возобновление процессов. В Windows понятия «приостановка» и «возобновление» неприменимы к процессам, так как они не участвуют в распределении процессорного времени. Приостановить все потоки определенного процесса можно сделать из другого процесса, причем он должен быть отладчиком и, в частности, вызывать функции WaitForDebugEvent и ContinueDebugEvent.

Других способов приостановки всех потоков процесса в Windows нет: программа, выполняющая такую операцию, может «потерять» новые потоки. Система должна как-то приостанавливать в этот период не только все существующие, но и вновь создаваемые потоки.

Поток может сообщить системе не выделять ему процессорное время на определенный период, вызвав:

VOID Sleep(DWORD dwMilliseconds);

Эта функция приостанавливает поток на dwMilliseconds миллисекунд. Особенности:

-вызывая Sleep, поток добровольно отказывается от остатка выделенного ему кванта времени;

-система прекращает выделять потоку процессорное время на период, примерно равный заданному;

-можно вызвать Sleep и передать в dwMilliseconds значение INFINITE, вообще запретив планировать поток;

-можно вызвать Sleep и передать в dwMilliseconds нулевое значение – т.е. отказаться от остатка своего кванта времени и заставить систему подключить к процессору другой поток.