844
Глава.29 .Примитивные.конструкции.синхронизации.потоков
более сложные конструкции аналогичного назначения, например
мьютексы
(mutex). Более полную информацию о них вы найдете в моей книге «Windows via
C/C++» (Microsoft Press, 2007).
В пространстве имен
System.Threading
существует
абстрактный базовый класс
WaitHandle
. Он играет роль оболочки для дескриптора ядра Windows. В FCL име-
ется несколько производных от него классов. Все они определены в пространстве
имен
System.Threading
и реализуются библиотекой
MSCorLib dll
. Исключением
является класс
Semaphore
, реализованный в библиотеке
System dll
. Вот как вы-
глядит иерархия этих классов:
WaitHandle
EventWaitHandle
AutoResetEvent
ManualResetEvent
Semaphore
Mutex
В базовом классе
WaitHandle
имеется поле
SafeWaitHandle
,
содержащее де-
скриптор ядра Win32. Это поле инициализируется в момент создания класса, про-
изводного от
WaitHandle
. Кроме того, класс
WaitHandle
предоставляет открытые
методы, которые наследуются всеми производными классами. Каждый из вызыва-
емых конструкциями режима ядра методов обеспечивает полную защиту памяти.
Вот наиболее интересные открытые методы класса
WaitHandle
(перегруженные
версии некоторых методов не показаны):
public abstract class WaitHandle : MarshalByRefObject, IDisposable {
// Реализация WaitOne вызывает функцию Win32 WaitForSingleObjectEx.
public virtual Boolean WaitOne();
public virtual Boolean WaitOne(Int32 millisecondsTimeout);
public virtual Boolean WaitOne(TimeSpan timeout);
// Реализация WaitAll вызывает функцию Win32 WaitForMultipleObjectsEx
public static Boolean WaitAll(WaitHandle[] waitHandles);
public static Boolean WaitAll(WaitHandle[] waitHandles,
Int32 millisecondsTimeout);
public static Boolean WaitAll(WaitHandle[] waitHandles, TimeSpan timeout);
// Реализация WaitAny вызывает функцию Win32 WaitForMultipleObjectsEx
public static Int32 WaitAny(WaitHandle[] waitHandles);
public static Int32 WaitAny(WaitHandle[] waitHandles,
Int32 millisecondsTimeout);
public static Int32 WaitAny(WaitHandle[] waitHandles, TimeSpan timeout);
public const Int32 WaitTimeout = 258; // Возвращается WaitAny
// в случае тайм-аута
// Реализация Dispose вызывает функцию Win32
// CloseHandle – НЕ ВЫЗЫВАЙТЕ ЕЕ!
public void Dispose();
}
845
Конструкции.режима.ядра
Здесь следует сделать несколько замечаний:
Метод
WaitOne
класса
WaitHandle
блокирует текущий
поток до активизации
объектом ядра. Он вызывает Win32-функцию
WaitForSingleObjectEx
. Значение
true
возвращается, если объект был активизирован. Если же время ожидания
истекло, возвращается значение
false
.
Статический метод
WaitAll
класса
WaitHandle
заставляет вызывающий поток
ждать активизации всех объектов ядра,
указанных в массиве
WaitHandle[]
.
Если все объекты были активизированы, возвращается значение
true
, в случае
же истечения времени ожидания возвращается значение
false
. Данный метод
вызывает Win32-функцию
WaitForMultipleObjectsEx
, передавая параметру
bWaitAll
значение
TRUE
.
Статический метод
WaitAny
класса
WaitHandle
заставляет вызывающий
поток ждать активизации любого из объектов ядра, указанных в массиве
WaitHandle[]
.
Возвращенное значение типа
Int32
является индексом ак-
тивизированного элемента массива. Если в процессе ожидания сигнала не
поступило, возвращается значение
WaitHandle.WaitTimeout
. Данный метод
вызывает Win32-функцию
WaitForMultipleObjectsEx
, передавая параметру
bWaitAll
значение
FALSE
.
Метод
Dispose
закрывает дескриптор объекта ядра. Во внутренней реализации
эти методы вызывают функцию Win32
CloseHandle
.
Вызывать
Dispose
в коде
можно только в том случае, если вы абсолютно уверены, что объект ядра не
используется другими потоками. Это обстоятельство сильно затрудняет напи-
сание и тестирование кода, поэтому я настоятельно не рекомендую вызывать
Dispose
; просто позвольте уборщику мусора выполнить свою работу. Он сможет
определить, когда объект не используется, и уничтожит его.
Do'stlaringiz bilan baham: