Событие
Объект типа событие (event) — простейший выбор для задач синхронизации. Он подобен дверному звонку — звенит до тех пор, пока его кнопка находится в нажатом состоянии, извещая об этом факте окружающих. Аналогично, и объект может быть в двух состояниях, а "слышать" его могут многие потоки сразу.
Класс TEvent (модуль SYNCOBJS.PAS) имеет два метода:
setEvent и ResetEvent, которые переводят объект в активное и пассивное состояние соответственно. Конструктор имеет следующий вид:
constructor Create(EventAttributes: PSecurityAttributes;
ManualReset, InitialState: Boolean; const Name: string);
Здесь параметр initialstate — начальное состояние объекта,
ManualReset — способ его сброса (перевода в пассивное состояние). Если этот параметр равен
True, событие должно быть сброшено вручную. В противном случае событие сбрасывается по мере того, как стартует хоть один поток, ждавший данный объект.
На третьем методе:
TWaitResult = (wrSignaled, wrTimeout, wrAbandoned, wrError);
function WaitFor(Timeout: DWORD): TWaitResult;
остановимся подробнее. Он дает возможность ожидать активизации события в течение
Timeout миллисекунд. Как вы могли догадаться, внутри этого
метода происходит вызов функции waitFotsingieObject. Типичных результатов на выходе
waitFor два — wrsignaied, если произошла активизация события, и
wrTimeout, если за время тайм-аута ничего не произошло.
Примечание
Если нужно (и допустимо!) ждать бесконечно
долго, следует установить параметр Timeout
в значение INFINITE.
Рассмотрим маленький пример. Включим в состав нового проекта объект типа
TThread, наполнив его метод
Execute следующим содержимым:
Var res: TWaitResult;
procedure TSimpleThread.Execute;
begin
e := TEvent.Create(nil,True,false, 'test');
repeat
e.ReSetEvent;
res := e.WaitFor(10000);
Synchronize(Showlnfo);
until Terminated; e.Free;
end;
procedure TSimpleThread.Showlnfo;
begin
ShowMessage(IntToStr(Integer (res)));
end;
На главной форме разместим две кнопки — нажатие одной из них запускает поток, нажатие второй активизирует событие:
procedure TForml.ButtonlClick(Sender: TObject);
begin
TSimpleThread.Create(False);
end;
procedure TForml.Button2Click(Sender: TObject);
begin
e.SetEvent;
end;
Нажмем первую кнопку. Тогда появившийся на экране результат (метод
Showlnfo) будет зависеть от того, была ли нажата вторая кнопка или истекли отведенные 10 секунд.
События используются не только для работы с потоками — некоторые процедуры операционной системы автоматически переключают их. К числу
таких процедур относятся отложенный (overlapped) ввод/вывод и события, связанные с коммуникационными портами.
|