Завершение фоновых задач по событию.
Одной из интересных особенностей библиотеки OTL в плане управления временем жизни фоновой задачи является - завершение фоновой задачи по событию. Как вы знаете фоновую задачу можно завершить, используя метод Terminate. Однако есть еще один способ завершения фоновой задачи – способ завершения по событию. Для этого используется метод TerminateWhen с объектом IOmniCancellationToken.
Идея метода состоит в том, что бы использовать одно событие для остановки множества задач сразу. Рассмотрим использование TerminateWhen на демонстрационном примере tests\14_TerminateWhen.test_14_TerminateWhen.pas Создание фоновых задач
TfrmTestTerminateWhen = class(TForm)
. . .
strict private
FCounter : IOmniCounter;
FTerminate: IOmniCancellationToken;
. . .
procedure TfrmTestTerminateWhen.btnStartTasksClick(Sender: TObject);
var
i: integer;
begin
if assigned(FCounter) and (FCounter.Value > 0) then
btnStopTasksClick(Sender);
FCounter := CreateCounter(10); // счетчик
FTerminate := CreateOmniCancellationToken; //сигнал остановки
for i := 1 to FCounter.Value do begin
Log(Format('Task started: %d',
[
CreateTask(TMyWorker.Create()).
TerminateWhen(FTerminate).
WithCounter(FCounter).
MonitorWith(OmniTED).
Run.
UniqueID
]));
end;
end;
Рассмотрим код более подробно. В секции strict private мы описываем две интерфейсных переменных. Одна FCounter – ссылается на счетчик (поддерживающий интерфейс IOmniCounter). Вторая переменная FTerminate – ссылается на класс, реализующий сигнальное событие.
Далее в методе btnStartTasksClick мы создаем класс реализующий интерфейс счетчика с помощью функции CreateCounter и присваиваем счетчику значение равное 10. После чего связываем данный класс с переменной FCounter.
Так-же мы создаем класс “сигнала-остановки” с помощью CreateOmniCancellationToken и так-же связываем его с интерфейсной переменной. Функции CreateCounter и CreateOmniCancellationToken определены в модуле OtlCommon.pas.
Разберем подробнее, класс сигнального события TOmniCancellationToken (реализующего интерфейс IOmniCancellationToken). Данный класс реализует стандартный Windows-объект синхронизации Event, служащий для создания события и имеющий два сигнальных состояния – отмеченное или неотмеченное.
Интерфейс IOmniCancellationToken
IOmniCancellationToken = interface ['{5946F4E8-45C0-4E44-96AB-DBE2BE66A701}']
function GetHandle: THandle;
//
procedure Clear;
function IsSignaled: boolean;
procedure Signal;
property Handle: THandle read GetHandle;
end; { IOmniCancellationToken }
Далее мы создаем 10 фоновых задач и связываем их с помощью метода TerminateWhen с интерфейсом сигнального события. После чего запускаем фоновые задачи на выполнение.
Теперь если мы хотим завершить работу всех запущенных ранее потоков нам нужно выставить наш объект FTerminate в сигнальное состояние, используя метод Signal. После выставление сигнала, внутренний механизм OTL увидит, что пришел сигнал “завершения задачи” и начнет закрывать фоновые задачи.
test_14_TerminateWhen.pas Завершение фоновых задач по событию
procedure TfrmTestTerminateWhen.btnStopTasksClick(Sender: TObject);
begin
if not assigned(FTerminate) then
Exit;
FTerminate.Signal; //Выставляем объект в сигнальное состояние
while FCounter.Value > 0 do begin // ugly, I know
Sleep(10);
Application.ProcessMessages;
end;
Log('All stopped');
end;
Комментариев нет:
Отправить комментарий