ActiveX в Delphi

       

Общий обзор потоков



Поток (Thread) - это объект операционной системы, заключенный в процесс и реализующий какую-либо задачу. Каждое приложение (процесс) Win32 имеет по крайней мере один поток, который называется главным (основным, стандартным). Каждый процесс может содержать несколько потоков.

Примечание
Так как применение потоков возможно только для 32-разрядных приложений, в 16-разрядной операционной системе приложения, использующие потоки, работать не будут.

Возможность введения многопоточности появилось с приходом вытесняющей многозадачности. В ранних, 16-разрядных версиях Windows использовалась кооперативная многозадачность.
Кооперативная многозадачность - поддержка "параллельной" работы нескольких приложений операционной системы, при которой передача управления операционной системе происходит от приложения. Данный вид многозадачности оказался весьма неэффективным. В случае "зависания" одного приложения, "зависала" вся система.
Вытесняющая многозадачность - вид многозадачности, когда управления потоками возложено полностью на операционную систему. Операционная система распределяет процессорное время для каждого потока в зависимости от его приоритетов. При этом, если зависает один из потоков, операционная система продолжает выделять процессорное время для выполнения других потоков.


В большинстве приложений вы можете использовать объект потока, который позволяет вам использовать потоки в ваших приложениях. Объекты потоков инкапсулируют в себе основные свойства и методы, необходимые для написания многопоточных приложений.
Итак, любой поток - это объект, получающий определенное процессорное время. Всякое приложение Windows является процессом операционной системы. Каждый процесс состоит хотя бы из одного потока, который называется главным. Вообще, Windows не ограничивает число потоков для каждого процесса.

Примечание
Объекты потоков не позволяют вам управлять атрибутами безопасности или размером стека ваших потоков. Для того чтобы контролировать их, вам необходимо использовать функцию BeginThread, которая рассматривается далее.

Для того чтобы использовать объекты потоков в вашем приложении, вам нужно создать потомок класса TThread.
Класс TThread был создан для облегчения написания приложений с несколькими потоками. Он гарантирует совместимость при работе с библиотекой визуальных компонентов (VCL) Delphi.
Вообще, при создании многопоточных приложений необходимо следовать приведенным ниже рекомендациям:
- остерегайтесь создавать слишком много потоков - это может привести к большой загруженности операционной системы и процессора. Рекомендуемое ограничение числа активных потоков в одном процессе - 16 (для однопроцессорной системы);
- используйте синхронизацию в случае, когда несколько потоков пытаются получить доступ к одному ресурсу;
- большинство методов, которые обращаются к объектам VCL и изменяют содержимое формы, должны вызываться из главного VCL-потока или использовать объект синхронизации, такой как TMultiReadExclusive-WriteSynchronizer.
Определение объекта TThread находится в модуле classes и имеет следующий вид (листинг 1.19):

Листинг 1.19
TThread = class private
FHandle: THandle; FThreadID: THandle; FTerminated: Boolean; FSuspended: Boolean; FFreeOnTerminate: Boolean; FFinished: Boolean; FReturnValue: Integer; FOnTerminate: TNotifyEvent; Method: TThreadMethod; FSynchronizeException: TObject; procedure CallOnTerminate; function GetPriority: TThreadPriority; procedure SetPriority(Value: TThreadPriority); procedure SetSuspended(Value: Boolean); protected
procedure DoTerminate; virtual;
procedure Execute; virtual; abstract;
procedure Synchronize(Method: TThreadMethod);
property ReturnValue: Integer read FReturnValue write FReturnValue;
property Terminated: Boolean read FTerminated;
public
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
procedure Resume;
procedure Suspend;
procedure Terminate;
function WaitFor: LongWord;
property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
property Handle: THandle read FHandle;
property Priority: TThreadPriority read GetPriority write SetPriority; property Suspended: Boolean read FSuspended write SetSuspended; property ThreadID: THandle read FThreadID;
property OnTerminate: TNotifyEvent read FOnTerminate write FQnTerminate; end;

Из вышеприведенного листинга можно определить, что объект TThread является прямым потомком объекта TObject, следовательно, он не является визуальным компонентом. Его метод Execute - абстрактный, а значит, сам объект TThread тоже является абстрактным, и вы не сможете создать экземпляр этого класса. Таким образом, вам придется определять классы-потомки данного класса для работы с потоками.
Для создания потомка класса TThread выберите в главном меню Delphi команду File/New (Файл/Новый), затем в появившемся окне (рис. 1.25) щелкните на Thread Object (Объект потока).
В открывшемся диалоговом окне напишите имя для вашего нового объекта потока. После всего этого Delphi создаст новый модуль и в окне редактора кода появится новая вкладка.
Рис. 1.25. Добавление объекта потока в проект с помощью диалогового окна New Items

Примечание
В отличие от большинства диалоговых окон IDE, которые требуют ввода имени класса, диалоговое окно создания нового объекта потока не добавляет автоматически букву "Т" перед названием вашего класса. Поэтому желательно самостоятельно правильно называть новые потоки, например TMyThread.

Если вы проделали все вышеописанное и назвали новый объект потока TMyThread, то в новом модуле, сгенерированном Delphi, вы можете увидеть код - заготовку для вашего нового объекта потока (листинг 1.20).

Листинг 1.20
unit Unit2;
interface
uses
Classes; type
TMyThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
implementation { TMyThread }
procedure TMyThread.Execute;
begin
{ Place thread code here } end;
end.

В автоматически сгенерированном файле модуля вы можете: - инициализировать поток;
- заполнить метод Execute объекта потока, разместив там функции и процедуры;
- написать код гарантированного разрушения потока (например, строку FreeOnTerminate:=True;).



Содержание раздела