Организация подзадач в Win32. Класс TThread

Организация подзадач в Win32.

Класс TThread.

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

Нужно отдавать себе отчет, что с точки зрения операционной системы, поток — это ее объект. При создании он получает дескриптор и отслеживается ОС. Объект класса TThread — это конструкция Delphi, соответствующая потоку ОС. Этот объект VCL создается до реального возникновения потока системе и уничтожается после его исчезновения.

Изучение класса TThread начнем с конструктора:

constructor Create(CreateSuspended: Boolean);

В качестве аргумента он получает параметр CreateSuspended. Если его значение равно True, вновь созданный поток не начинает выполняться до тех пор, пока не будет сделан вызов метода Resume. В случае, если CreateSuspended имеет значение False, поток начинает исполнение и конструктор завершается.

destructor Destroy; override;

Деструктор Destroy вызывается, когда необходимость в созданном потоке отпадает. Деструктор завершает его и высвобождает все ресурсы, связанные с объектом TThread.

procedure Resume;

Метод Resume класса TThread вызывается, когда поток возобновляется после остановки, или если он был создан с параметром createsuspended, равным True.

procedure Suspend;

Вызов метода suspend приостанавливает поток с возможностью запуска впоследствии. Метод suspend приостанавливает вне зависимости от кода, исполняемого потоком в данный момент; выполнение продолжается с точки останова.

property Suspended: Boolean;

Свойство suspended позволяет программисту определить, не приостановлен ли поток. С помощью этого свойства можно также запускать и останавливать поток. Установив suspended в True, вы получите тот же результат, что и при вызове метода suspend — приостановку. Наоборот, установка suspended в False возобновляет выполнение потока, как и вызов метода Resume.

function Terminate: Integer;

Для окончательного завершения потока (без последующего запуска) существует метод Terminate; он останавливает поток и возвращает управление вызвавшему процессу только после того, как это произошло. Значение, возвращаемое функцией Terminate, соответствует состоянию потока. Примерами возможных состояний являются случай нормального завершения и случай, когда к моменту вызова Terminate поток уже завершился (или был завершен из другого потока). Метод Terminate автоматически вызывается и из деструктора объекта. В явном виде его, за редким исключением, вызывать не надо.

Property Terminated: Boolean;

Свойство Terminated позволяет узнать, произошел ли уже вызов метода Terminate или нет.

Function WaitFor: Integer;

Метод WaitFor предназначен для синхронизации и позволяет одному потоку дождаться момента, когда завершится другой поток. Если вы внутри потока FirstThread пишете код: Code:= SecondThread.WaitFor. Это это означает, что поток FirstThread останавливается до момента завершения потока SecondThread. Метод WaitFor возвращает код завершения ожидаемого потока.

property Handle: THandle read FHandle;

property ThreadID: THandle read FThreadID;

Свойства Handle и ThreadiD дают программисту непосредственный доступ к потоку средствами API Win 32. Если разработчик хочет обратиться к потоку и управлять им, минуя возможности класса TThread, значения Handle и ThreadID могут быть использованы в качестве аргументов функций Win 32 API. Например, если программист хочет перед продолжением выполнения приложения дождаться завершения сразу нескольких потоков, он должен вызвать функцию API waitForMuitipieObjects; для ее вызова необходим массив дескрипторов потоков.

property Priority: TThreadPriority;

Свойство priority позволяет запросить и установить приоритет потоков. Приоритет определяет, насколько часто поток получает время процессора. Естественно, программист захочет выделить главному потоку в приложении большее время, а потоку, например, с фоновой проверкой орфографии — меньшее. Допустимыми значениями приоритета являются tpidle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest и tpTimeCritical. Будьте осторожны, используя приоритеты tpHighest и tpTimeCritical. Оба они могут оказать влияние на выполнение приложения, а последний — и на всю операционную систему.

procedure Synchronize(Method: TThreadMethod);

Этот метод относится к секции protected, то есть может быть вызван только из потомков TThread. Delphi предоставляет программисту метод synchronize для безопасного вызова методов VCL внутри потоков. Во избежание ситуаций гонок, метод Synchronize дает гарантию, что к каждому объекту VCL одновременно имеет доступ только один поток. Аргумент, передаваемый в метод synchronize, — это имя метода, который производит обращение к VCL; вызов synchronize с этим параметром — это то же, что и вызов самого метода. Такой метод (класса TThreadMethod) не должен иметь никаких параметров и не должен возвращать никаких значений. К примеру, в основной форме приложения нужно предусмотреть функцию

procedure TMainFom.SyncShowMessage;

begin

ShowMessage(IntToStr(Listi.Count));

//другие обращения к VCL

end;

a в потоке для показа сообщения писать не

ShowMessage(IntToStr(List1.Count));

А только так:

Synchronize(MainFonn.SyncShowMessage);

Производя любое обращение к объекту VCL из потока, убедитесь, что при этом используется метод Synchronize; в противном случае результаты могут оказаться непредсказуемыми.

Procedure Execute; virtual; abstract;

Это и есть главный метод объекта TThread. В его теле должен содержаться код, который и представляет собой собственно поток. Метод Execute класса tThread объявлен как абстрактный.

Переопределяя метод Execute, мы можем тем самым закладывать в новый потоковый класс то, что будет выполняться при его запуске. Если поток был создан с аргументом CreateSuspended, равным False, то метод Execute выполняется немедленно, в противном случае Execute выполняется после вызова метода Resume.

Если поток рассчитан на однократное выполнение каких-либо действий, то никакого специального кода завершения для него писать не надо. После выполнения метода Execute будет вызван деструктор, который сделает все необходимое.

Если же в потоке будет выполняться какой-то цикл, и поток должен завершиться вместе с приложением, то условия окончания цикла должны быть примерно такими:

procedure TMyThread.Execute;

begin

repeat

DoSomething;

Until CancelCondition or Terminated;

End;

здесь CancelCondition — ваше личное условие завершения потока (исчерпание данных, поступление на вход того или иного символа и т. п.), свойство Terminated говорит о завершении потока извне (скорее всего, завершается породивший его процесс).

С завершением потока надо быть очень внимательным, — если он зациклился и не реагирует на сигналы завершения, то зависнет все приложение.

property ReturnValue: Integer;

Свойство ReturnValue позволяет узнать и установить значение, возвращаемое потоком по его завершении. Эта величина полностью определяется пользователем. По умолчанию поток возвращает ноль, но если программист захочет вернуть другую величину, то простая переустановка свойства ReturnValue внутри потока позволит получить эту информацию другим потокам.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: