Класс потока в Delphi
Раптор [Ментальная студия]
http://mental.mentsu.com
(один)
В Delphi существует класс потока TThread, который используется для реализации многопоточного программирования. В большинстве книг по Delphi это упоминается, но в основном они дают краткое введение в несколько членов класса TThread, а затем объясняют реализацию и использование функции Execute. Синхронизация завершена. Однако это еще не все многопоточное программирование. Цель написания этой статьи — дополнить это.
Поток — это, по сути, часть кода, выполняющаяся одновременно в процессе. Процесс имеет по крайней мере один поток, так называемый основной поток. Одновременно может существовать несколько подпотоков. Когда в процессе используется более одного потока, это называется «многопоточностью».
Так как же определяется этот так называемый «кусок кода»? По сути, это функция или процесс (для Delphi).
Если вы используете Windows API для создания потока, это реализуется через функцию API под названием CreateThread, которая определяется как:
РУЧКА CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWord dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
ЛПДВОРД lpThreadId
);
Как следует из их названий, параметрами являются: атрибуты потока (используются для установки атрибутов безопасности потока в NT, недействительны в 9X), размер стека, начальный адрес, параметры, флаг создания (используется для установки состояния потока при создании), идентификатор потока, и, наконец, возвращает дескриптор потока. Начальный адрес является входом в функцию потока. Пока функция потока не завершится, поток завершается.
Процесс выполнения всего потока выглядит следующим образом:
Поскольку CreateThread имеет множество параметров и является Windows API, в библиотеке времени выполнения C предусмотрена общая функция потока (теоретически ее можно использовать в любой ОС, поддерживающей потоки):
unsigned long _beginthread(void (_USERENTRY *__start)(void *), unsigned __stksize, void *__arg);
Delphi также предоставляет аналогичную функцию с той же функциональностью:
функция BeginThread (SecurityAttributes: Pointer; StackSize: LongWord; ThreadFunc: TThreadFunc; Параметр: Pointer; CreationFlags: LongWord; var ThreadId: LongWord): Integer;
Функции этих трех функций в основном одинаковы. Все они помещают код функции потока в независимый поток для выполнения. Самая большая разница между функциями потока и общими функциями заключается в том, что как только функция потока запускается, эти три функции запуска потока продолжают выполняться вниз, в то время как функция потока выполняется в независимом потоке. Как долго это происходит. принять для выполнения? Когда он возвращается, основной поток не заботится и не знает.
В обычных обстоятельствах после возврата из функции потока поток завершается. Но есть и другие способы:
API Windows:
VOID ExitThread (DWORD dwExitCode);
Библиотека времени выполнения C:
недействительный _endthread (недействительный);
Библиотека времени выполнения Delphi:
PROcedure EndThread (ExitCode: Integer);
Чтобы записать некоторые необходимые данные потока (статус/свойства и т. д.), ОС создаст внутренний объект для потока. Например, в Windows дескриптор является дескриптором этого внутреннего объекта, поэтому этот объект следует освободить. когда нить закончится.
Хотя многопоточное программирование можно легко выполнить с помощью API или RTL (библиотеки времени выполнения), все же требуется более детальная обработка. По этой причине Delphi улучшил инкапсуляцию потоков в модуле «Классы». Это класс потока VCL: TThread.
Использование этого класса также очень просто. В большинстве книг по Delphi говорится, что его основное использование заключается в следующем: сначала создайте собственный класс потока из TThread (поскольку TThread является абстрактным классом и не может генерировать экземпляры), а затем используйте абстрактный метод Override: Execute( This). — это функция потока, которая является частью кода, выполняемого в потоке). Если вам нужно использовать визуальный объект VCL, вам нужно сделать это через процесс синхронизации. Для получения более подробной информации мы не будем здесь вдаваться в подробности. Пожалуйста, обратитесь к соответствующим книгам.
Следующее, о чем пойдет речь в этой статье, — это то, как класс TThread инкапсулирует потоки, то есть углубленное изучение реализации класса TThread. Потому что только по-настоящему поняв это, мы сможем использовать его лучше.
Ниже приведено объявление класса TThread в DELPHI7 (в этой статье обсуждается только реализация под платформу Windows, поэтому весь код, относящийся к платформе Linux, был удален):
TThread = класс
частный
FHandle: THandle;
FThreadID: THandle;
FCreateSuspended: логическое значение;
FTerminate: Логическое значение;
FSuspended: логическое значение;
FFreeOnTerminate: логическое значение;
FЗавершено: логическое значение;
FReturnValue: целое число;
FOnTerminate: TNotifyEvent;
ФСинхронизе: ТСинхронизерекорд;
FFatalException: TObject;
процедура CallOnTerminate;
процедура класса Synchronize (ASyncRec: PSynchronizeRecord перегрузка);
функция GetPriority: TThreadPriority;
процедура SetPriority (Значение: TThreadPriority);
процедура SetSuspended (Значение: логическое);
защищенный
процедура CheckThreadError (ErrCode: целочисленная перегрузка);
процедура CheckThreadError (Успех: логическая перегрузка);
процедура DoTerminate виртуальная;
процедура Выполнить виртуальная;
процедура Synchronize (Метод: перегрузка TThreadMethod);
свойство ReturnValue: Целочисленное чтение FReturnValue запись FReturnValue;
свойство прекращено: логическое чтение FTerminate;
общественный
конструктор Create(CreateSuspended: Boolean);
деструктор Уничтожить;
переопределение процедуры AfterConstruction;
Резюме процедуры;
процедураПриостановить;
процедура Завершить;
функция WaitFor: LongWord;
процедура класса Synchronize (AThread: TThread; AMethod: TThreadMethod перегрузка);
процедура класса StaticSynchronize(AThread: TThread; AMethod: TThreadMethod);
свойство FatalException: TObject читает FFatalException;
свойство FreeOnTerminate: логическое чтение FFreeOnTerminate запись FFreeOnTerminate;
дескриптор свойства: THandle прочитано FHandle;
Приоритет свойства: TThreadPriority чтение GetPriority запись SetPriority;
свойство Suspended: Boolean read FSuspended write SetSuspended;
свойство ThreadID: Thandle читает FThreadID;
свойство OnTerminate: TNotifyEvent чтение FOnTerminate запись FOnTerminate;
конец;
Класс TThread — относительно простой класс в RTL Delphi. В нем не так много членов, а атрибуты класса очень просты и понятны. В этой статье будет проведен подробный анализ только нескольких более важных методов-членов класса и единственного события: OnTerminate. .
(продолжение следует)