OOP Course
Сьогодні

Підрозділ 15.5

Клас AutoResetEvent

15.5. Клас AutoResetEvent Monitor.Wait і Monitor.Pulse — потужні інструменти координації, але вони вимагають, щоб і виробник, і споживач використовували один і той самий об'єкт замку . У складніших сценаріях, д

15.5. Клас AutoResetEvent

Monitor.Wait і Monitor.Pulse — потужні інструменти координації, але вони вимагають, щоб і виробник, і споживач використовували один і той самий об'єкт замку. У складніших сценаріях, де потоки координуються через незалежні сигнали, більш природним є клас AutoResetEvent.

AutoResetEvent — це примітив синхронізації, що моделює автоматичне скидання сигнального прапорця. Він має два стани:

  • Сигнальний (signaled, «зелене світло»): потоки, що чекають через WaitOne(), можуть продовжити виконання
  • Несигнальний (non-signaled, «червоне світло»): потоки блокуються на WaitOne()

Ключова особливість, яка відрізняє AutoResetEvent від ManualResetEvent: після того як один очікуючий потік пройшов через WaitOne(), прапорець автоматично скидається у несигнальний стан. Наступний потік знову буде заблокований — доки не надійде новий сигнал. Це нагадує турнікет: пропускає одного і автоматично закривається.

API класу AutoResetEvent

Метод / конструктор Опис
new AutoResetEvent(bool initialState) Створює об'єкт. true — початково сигнальний, false — несигнальний
Set() Переводить у сигнальний стан. Один очікуючий потік пройде через WaitOne(), після чого стан знову стане несигнальним
Reset() Примусово переводить у несигнальний стан
WaitOne() Блокує поточний потік до отримання сигналу
WaitOne(int ms) Блокує з таймаутом. Повертає true, якщо сигнал надійшов, false — якщо час вичерпано

Клінічний приклад: відправка результатів аналізу

Лаборант завершує аналіз і сигналізує лікарю, що результати готові. Лікар чекає сигналу, перш ніж відкрити результати:

Після виклику resultsReady.Set() лікар отримує сигнал і прокидається. Прапорець автоматично скидається у несигнальний стан — якщо б з'явився ще один лікар, що чекає, він знову заблокувався б до наступного Set().

Координація кількох етапів: конвеєр обробки

AutoResetEvent особливо зручний для організації послідовних етапів конвеєра, де кожен наступний крок починається тільки після завершення попереднього. У клінічній системі: реєстрація → огляд → аналізи → призначення — кожен крок сигналізує готовність наступному:

Усі чотири потоки запущені одночасно, але виконуються суворо по черзі: кожен чекає сигналу від попереднього через відповідний AutoResetEvent. Це ефективніше за послідовний запуск потоків: поки реєстратура реєструє, лікар і лабораторія вже «готові» і не витрачають час на ініціалізацію.

WaitOne з таймаутом

Якщо потік не може чекати нескінченно — наприклад, після 5 секунд очікування слід надіслати сповіщення адміністратору — використовується WaitOne(ms):

WaitOne(ms) дає потоку можливість «зупинитись і перевірити» — реалізація тайм-аутів без зайвого ускладнення коду.

AutoResetEvent vs ManualResetEvent

AutoResetEvent скидає прапорець автоматично після пробудження одного потоку. Якщо ж потрібно одночасно «відкрити ворота» для всіх очікуючих потоків і тримати їх відкритими до явного скидання, використовується ManualResetEvent:

Характеристика AutoResetEvent ManualResetEvent
Скидання після WaitOne Автоматично Вручну через Reset()
Пропускає через Set() Один потік Всі очікуючі
Аналогія Турнікет Відкриті ворота
Типовий сценарій Передача одного завдання конкретному виконавцю Старт усіх потоків одночасно

У медичному контексті: AutoResetEvent — це черговий реєстратор, що передає один квиток одному пацієнту; ManualResetEvent — це оголошення по радіо, що відкривається кабінет і туди одночасно йдуть усі пацієнти, яким призначено.

Розроблено Tomka Yurii · © 2026 ·