П ути
потоков
неисповедимы
Щ Р
Сергей МАСЛ1/1КОВ
Создание потока
К
аждый раз при запуске приложения система создает
про-
цесс.
Процесс — это и есть программа. При запуске про-
цесса система создает в нем первичный поток исполнения.
Система делает это автоматически, и если программист не
предпринимает каких-либо действий по созданию второго пото-
ка, то первичный поток и процесс, в котором он выполняется,
обычно отождествляются в сознании пользователя. Но вы долж-
ны помнить, что это разные вещи!
Так как одного потока нам будет маловато ©, с помощью функ-
ции
C r e a t e T h r e a d ( ) создадим еще несколько — они будут выпол-
няться в одном адресном пространстве, принадлежащем процес-
су. Когда создаются дополнительные потоки, родительский про-
цесс начинает выполняться не последовательно, а
параллельно.
Все процессы потока, равно как и потоки разных процессов, вы-
полняются хотя и параллельно, но не одновременно, а по очере-
ди, вытесняя друг друга по мере выделения им
квантов процессор-
ного времени
(величина кванта времени зависит от О С и типа
процессора). На многопроцессорном компьютере операционные
системы Windows
NT,
Windows ХР, Windows 2000 могут закрепить
за каждым процессором свой поток, что, естественно повысит ско-
рость роботы. Каждый поток в свою очередь должен иметь глав-
ную (рабочую) функцию, каковая должна иметь прототип
d w o r d
w i n a p i и м я ф у н к ц и и
(
l p v o i d )
, где
l p v o i d
— указатель на тип
v o i d (почти все windows-типы описаны в файлах
windef.h, winuser.h).
Теперь немного о самой функции
C r e a t e T h r e a d ( ) . О н а име-
ет следующий прототип:
H A N D L E C r e a t e T h r e a d (
L P S E C U R I T Y A T R I B U T E S l p T h r e a d A t t r i b u t e s , / /
Указатель
на атрибуты защиты потока
D W O R D d w S t a c k S i z e , / /
Начальный размер стека потока
L P T H R E A D _ S T A R T _ _ R O U T I N E I p S t a r t A d d r e s s , / /
Адрес функ-
ции потока
L P V O I D I p P a r a m e t e r
,11
Аргумент, передаваемый новому
потоку
D W O R D d w C r e a t i o n F l a g s , / /
Флаги создания
L P D W O R D l p T h r e a d l d / /
Адрес переменной для возврата
идентификатора потока
) ;
Параметр
l p T h r e a d A t t r i b u t e s характеризует атрибуты за-
щиты создаваемого потока. Этот параметр в прикладных про-
граммах может быть выставлен в
N U L L .
Параметр
d w S t a c k S i z e определяет объем адресного про-
странства, выделяемый под стек потока. Лучше всего, чтобы этот
параметр был ровен нулю, тогда размер стека определяется из
настроек компоновщика.
Параметр
I p S t a r t A d d r e s s задает адрес функции потока, ко-
торая и будет выполняться.
Следующий параметр
I p P a r a m e t e r — это те данные, кото-
рые будут переданы в функцию потока при ее активизации. Ес-
ли вам надо передать в функцию набор параметров, то следу-
ет использовать структуру данных и, соответственно, передавать
в функцию указатель на структуру.
С помощью параметра
d w C r e a t i o n F l a g s можно создать «за-
мороженный поток»
( d w C r e a t i o n F l a g s = C R E A T E _ S A S P E N D E D ) , ко-
торый начнет выполняться только после вызова функции
R e -
s u m e T h r e a d O . Если параметр равен нулю, то поток начинает
выполняться немедленно после создания.
И последний параметр —
l p T h r e a d l d — представляет собой
адрес переменной
D W O R D , в которую функция C r e a t e T h r e a d ( )
при успешном завершении вернет идентификатор потока.
При успешном завершении функция
C r e a t e T h r e a d ( ) возвра-
щает дескриптор потока типа
h a n d l e ,
а если что-то не так, то-
гда вернет
N U L L .
Обмен информацией между потоками
Обмен информации может осуществляться несколькими спо-
собами:
через файл,
через
проекцию файла в памяти
или путем
отправки сообщений.
Однако следует заметить, что наиболее
простым способом будет
обмен информацией через глобальные
переменные.
Это обусловлено тем, что все потоки процесса ра-
ботают в одном адресном пространстве, следовательно, всем
потокам доступны глобальные переменные этого процесса. Ино-
гда нужно сообщить главному потоку, что задача, которая вы-
полнялась дочерним потоком, завершена. В этом случае можно
воспользоваться механизмом передачи сообщений или синхро-
низацией (об этом дальше). Для отправки сообщений использу-
ется функция
S e n d M e s s a g e O , имеющая следующий прототип:
L R E S U L T S e n d M e s s a g e (
H W N D h w n d , / /
Дескриптор окна
,
в которое следует пере-
дать сообщение
U I N T u M s g ,
/ / Код сообщения
W P A R A M w P a r a m ,
// Первый параметр сообщения
L P A R A M / /
Второй параметр сообщения
Конечно, в программе должен содержаться код обработки
сообщений, а иначе зачем мы сообщения посылаем ©? Сооб-
щения лучше использовать для заранее определенных действий
(например, я использовал их для отправки сообщения
w m _ p a i n t ,
чтобы перерисовать окно).
Вариант отправки сообщений хорош, но его лучше исполь-
зовать при обмене информацией между процессами. Если вам
нужно отправить блок данных в другой процесс, используйте со-
общение
WM C O P Y D A T A , в качестве косвенного параметра кото-
рого может выступать адрес массива данных. Использование со-
общения
w m _ c o p y d a t a
требует наличия в программе структур-
ной переменной типа
c o p y d a t a s t r u c t :
t y p e d e f s t r u c t t a g C O P Y D A T A S T R U C T {
D W O R D d w D a t a ; / /
любой параметр, передаваемый процессу-
приемнику
D W O R D c b D a t a ; / /
Размер в байтах передаваемых данных
P V O I D l p D a t a ; / /
Адрес передаваемых данных
} C O P Y D A T A S C T U C T ;
Для использования структуры
c o p y d a t a s c t u c t в
программе
должен быть описан макрос, который будет обрабатывать сооб-
щение
w m _ c o p y d a t a .
Вот этот макрос:
# d e f i n e H a n d le _ _ W M _ C O P Y D A T A (h w n d , l P a r a m , f n ) \
( ( £ n ) ( ( h w n d ) , (H W N D ) ( w p P a r a m ) ,
( C O P Y D A T A S T R U C T * ) ( I P a r a m ) ) ? 1 L : 0 L )
Этот макрос написан по принципу макроса
h a n d l e _ m s g
(cm. win-
dowsx.h). Но я отвлекся, вернемся к потокам.
У каждого потока (как и процесса) есть свой приоритет. При
создании потока ему приписывается приоритет
t h r e a d
p r i o r -
I T Y _ N 0 R M A 1 . Всего приоритетов семь: t h r e a d _ p r i o r i t y _ i d l e ,
T H R E A D _ P R I O R I T Y ^ L O W E S T , T H R E A D . P R I O R I T Y B E L O W N O R M A L ,
T H R E A D _ P R I O R I T Y
n o r m a l ,
t h r e a d _ p r i o r i t y _ a b o v e
n o r m a l ,
T H R E A D _ P R I O R I T Y _ H I G H E S T И T H R E A D P R I O R I T Y . T I M E C R I T I -
C A L . Программист может для каждого потока установить приори-
тет, вызвав функцию
S e t T h r e a d P r i o r i t y (H A N D L E h T h r e a d , i n t
P r i o r i t y ) . Как видно, мы передаем в качестве первого пара-
метра дескриптор потока. Для определения текущего уровня при-
оритета применяется функция
G e t T h r e a d P r i o r i t y ( H A N D L E
h T h r e a d ) , которая возвращает параметр типа i n t . Типичная
схема игры с приоритетами — повышение уровня приоритета до
T H R E A D _ P R I O R I T Y _ A B O V E _ N O R M A L И ЛИ T H R E A D _ P R I O R I T Y _ H I G H -
E S T . Это делается для потоков, которые должны быстро реаги-
ровать на действия пользователя. Главное — с умом подходить
к этому, иначе может произойти ситуация, когдо будут выполнять-
ся только потоки с высоким приоритетом, а те, что с низким, бу-
дут скромно ждать своей очереди ©. Однако система может са-
предыдущая страница 40 Мой Компьютер 2004 41 читать онлайн следующая страница 42 Мой Компьютер 2004 41 читать онлайн Домой Выключить/включить текст