Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Реализация параллельного потока

Введение | Синхронизация потоков | Потоки и дескрипторы | Взаимодействие с VCL-потоком | Разделяемые данные | Асинхронное взаимодействие | Синхронное взаимодействие |


Читайте также:
  1. B) воздушного потока
  2. IV.Реализация государственной семейной политики на региональном уровне
  3. S 47. ТЕХНОЛОГИЧЕСКИЕ ОСНОВЫ ОПЕРАТИВНОГО УПРАВЛЕНИЯ МАТЕРИАЛЬНЫМИ ПОТОКАМИ
  4. Анализ пассажиропотока автобусного маршрута. Расчёт объёмов перевозок и пассажиропотока.
  5. Арест и реализация имущества должника-организации
  6. Асимметричный срыв потока.
  7. Базовый класс исключений, конструкторы, реализация собственного класса исключений

В качестве базового класса для потоков вполне можно использовать стандартный Delphi-класс TThread. Но для полноты картины в этом разделе статьи будет приведена другая реализация базового класса для параллельных потоков. В следующем разделе более подробно будет рассмотрен арбитр-менеджер потоков.

Класс, который предлагается в качестве кандидата для базового класса параллельных потоков, будет иметь только самую важную функциональность, то есть:

Последнее требование нуждается в некотором разъяснении. Дело в том, что библиотека VCL, предоставляющая Delphi-приложениям различные визуальные компоненты, не является потокобезопасной. Это означает, что прямой вызов методов визуальных компонентов из различных потоков почти наверняка разрушит работу приложения. При работе с параллельными потоками требуется обеспечить синхронизацию таким образом, чтобы методы визуальных компонентов вызывались только из основного потока приложения (VCL-потока). Класс TThread решает эту проблему с помощью метода Synchronize, который организует вызов некоторого метода в контексте основного потока и корректно обрабатывает возникающие исключительные ситуации.

Приведем определение класса параллельного потока, полный код вы можете посмотреть в файле GsvThread.pas, который прилагается к статье.

TGsvThread = classpublic constructor Create; destructor Destroy; override; private // эти поля нужны для менеджера потоков FManager: TGsvThreadManager; FGsvHandle: Integer; FRefCount: Integer; FCollision: TGsvThread; // это собственные данные объекта потока FSysHandle: THandle; FTerminated: Boolean; FFinished: Boolean; FTerminationEvent: THandle; procedure ThreadExecute; procedure Terminate; function GetPriority: Cardinal; procedure SetPriority(const Value: Cardinal); protected procedure Execute; virtual; abstract; procedure OnError(const E: Exception); virtual; procedure OnFinished; virtual; procedure Pause(aTime: Cardinal); property Terminated: Boolean read FTerminated write FTerminated; public procedure Resume; procedure Suspend; property GsvHandle: Integer read FGsvHandle; property SysHandle: THandle read FSysHandle; property Finished: Boolean read FFinished; property Priority: Cardinal read GetPriority write SetPriority; property TerminationEvent: THandle read FTerminationEvent;end;

С помощью конструктора мы можем создавать объект потока, метод Suspend позволяет приостановить поток, метод Resume запустить его после приостановки. Метод Suspend может быть вызван многократно, но каждому Suspend должен соответствовать парный вызов Resume. Свойство Priority позволяет получить и изменить приоритет потока. Это минимальная внешняя функциональность, которую мы предполагаем получить от потока. Внутренняя функциональность более сложна. Алгоритм работы потока определяется в наследуемом методе Execute. Если поток выполняет некоторую циклическую работу, то метод может выглядеть так:

procedure TDerivedThread.Execute;begin // действия до начала цикла.... // циклическое выполнение while not Terminated do begin.... end;end;

То есть, поток выполняется циклически до тех пор, пока у потока есть "пользователи". Кроме того, поток может самостоятельно прервать свое выполнения, выйдя из цикла или установив свойство Terminated в True. Если действия потока нециклические, то он просто выполняется от начала до конца. При возникновении ошибок вызывается метод OnError, которому передается объект возникшего исключения. При завершении работы потока (а, точнее, объекта ядра операционной системы) вызывается метод OnFinished. Отметим, что метод OnFinished будет вызван всегда, независимо от вызова метода OnError. Эти методы переопределяются в наследуемых классах. С помощью указанных методов можно определить все аспекты старта, выполнения и завершения параллельного потока.

Поток может самостоятельно приостановиться на некоторое время с помощью метода Pause, аргумент которого - время в миллисекундах. Время может быть равно 0, это означает, что поток отказывается от кванта времени, который выделен ему операционной системой и разрешает операционной системе переключиться на другой параллельный поток с тем же приоритетом. Если таких потоков нет, то Pause(0) не выполняет каких-либо действий. Рассмотрим реализацию метода Pause подробнее.

procedure TGsvThread.Pause(aTime: Cardinal);begin if not FTerminated then begin if aTime = 0 then Sleep(0) else WaitForSingleObject(FTerminationEvent, aTime); end;end;

Приостановка выполняется только в том случае, если поток еще не завершен и менеджер потоков не вызвал завершающий метод Terminate. Если время равно 0, то вызывается Windows-функция Sleep, а иначе выполняется ожидание события FTerminationEvent с таймаутом, равным времени паузы. Событие FTerminationEvent создается в конструкторе объекта потока, его назначение - быстрое завершение потока, если он находится состоянии ожидания некоторого события. Это довольно важный момент. Если мы хотим завершить программу, а поток ожидает некоторого события (которое, возможно уже никогда не произойдет или произойдет через неопределенное время), то у нас должен быть способ форсированного вывода потока из состояния ожидания. Более подробно событие TerminationEvent будет рассмотрено при обсуждении альтернативного ожидания. Событие устанавливается в методе Terminate:

procedure TGsvThread.Terminate;begin if not FTerminated then begin FTerminated:= True; SetEvent(FTerminationEvent); Resume; end;end;

Напомню, что предлагаемая техника основана на том, что временем жизни объекта потока управляет только менеджер потоков, поэтому другие потоки не могут вызывать напрямую метод Terminate, а тем паче Free - вместо этого они должны вызывать метод менеджера Release, чтобы сообщить о своем отказе от того или иного потока.


Дата добавления: 2015-07-20; просмотров: 49 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Подсчет ссылок| Менеджер потоков

mybiblioteka.su - 2015-2024 год. (0.008 сек.)