Interface
Uses Classes; Type MyThread = class (TThread) Private { Private declarations } protected procedure Execute; override; End; Implementation { Важно: Методы и свойства объектов из библиотеки визуальных компонентов могут использоваться только в рамках вызова метода Synchronize, например: Synchronize(UpdateCaption); где метод UpdateCaption должен быть подобен такому procedure MyThread.UpdateCaption; Begin Formi.Caption:= 'Новый текст метки'; end; } (MyThread } procedure MyThread.Execute; Begin { Пожалуйста, поместите код потока в этом месте } End; End. Программирование потока ничем не отличается от программирования обычной программы за одним важным исключением: поток не должен использовать методы и свойства визуальных компонен тов, которые приводят к изменению внешнего вида программа Точнее, он может это делать только при обращении к специальному методу synchronize, с помощью которого осуществляется синхронизация исполнения главного потока программы с дополнительным потоком. Для иллюстрации приемов работы с потоком создадим программу, которая будет непрерывно обновлять содержимое многострочного редактора и при этом осуществлять математические вычисления. Для ее создания сначала на пустую форму поместите панель TPpanel, очистите ее свойство caption и поместите в Align значение аlRight - эта панель предназначена для размещения редактора TSpinEdit, кнопки TButton и индикатора TGauge и всегда должна располагаться в правой части окна программы. Поместите на панель перечисленные компоненты так, как это показано на рисунке (компоненты TSpinEdit и TGuage находятся на странице samples палитры компонентов). Установите в свойство SpinEditl.Value 3начение 2, присвойте свойству Gaugel. Kind значение gkPie, Gaugel. BorderStyle-bsNone и Button1.Caption — 'Квадрат'. На свободное место формы положите компонент TMemo и установите для него в свойство Align значение alСlient, а свойство Name- 'mmOutput'. Теперь создадим обработчик события Button1.Click: при нажатии на кнопку вначале содержимое редактора SpinEdit1 возводится в квадрат до тех пор, пока отображаемое в нем значение не слишком большим (больше 10+1233). В этот момент надпись на кнопке меняется на “корень”, а нажатие на нее вычисляет корень квадратный ИЗ величины SpinEdit1. Дважды щелкните по кнопке Button1и напишите такой код: procedure TFormI.ButtonlClick(Sender: TObject); Begin if Tag=0 then Begin SpinEditl.Text:= Float-ToStr(sqr(StrToPloat(SpinEditl.Text))); if StrToFloat(SpinEditl.Text) > 1el233 then Begin Tag := 1; Buttoni.Caption:= 'Корень' End End Else Begin SpinEditl.Text:= FloatToStr(sqrt(StrToFloat(SpinEditl.Text))); if StrToFloat(SpinEditl.Text) < 2 then Begin SpinEditl.Value := 2; Tag:= 0; Button1.Caption:= 'Квадрат' End End End; Таким образом, главный код программы связан с извлечением корня или возведением в квадрат величины, записанной в редакторе SpinEditl. Теперь создадим модуль потока, в методе Execute которого будем непрерывно формировать по 100 строк в редакторе mmOutput и показывать процент заполнения редактора с помощью индикатора Gaugel. Выберите пиктограмму модуля потока в окне репозитория Delphi и дайте наследнику класса Thread имя ThreadDemo. Окончательный текст модуля потока представлен ниже. unit Unit2; Interface Uses Classes; Type ThreadDemo = class (TThread) private { Private declarations } protected S: String; N: Integer; procedure UpdateMemo; procedure UpdateGauge; procedure Execute; override; End; Var TDemo: ThreadDemo; Implementation uses Uniti,SysUtils; Important: Methods and properties of objects in VCL can only re used.in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure ThreadDemo.UpdateCaption; begin Formi.Caption:= 'Updated in a thread'; end; } ThreadDemo } procedure ThreadDemo.Execute; Var j, k: Integer; Begin Repeat S:=''; Synchronize(UpdateMemo); for k:= 0 to 99 do begin N:= k; S: = ' '; for j:= 1 to 20 do S:= S+FormatFloat('00',k), Synchronize(UpdateMemo); Synchronize(UpdateGauge) End; until False End; Procedure ThreadDemo.UpdateMemo; Begin with. Form1.mmOutput.Lines do if S=' ' then Clear else Add(S) End; Procedure ThreadDemo.UpdateGauge; Begin Form1.Gaugel.Progress := N End; End. Если вы запустите таким способом подготовленную программу, то ничего не произойдет - ведь мы еще не запустили поток. Чтобы сделать это, добавьте в модуле Unit1 главной формы ссылку uses Unit1, раскройте в окне Инспектора объектов список компонентов, выберите компонент Form1 и на его странице Event дважды щелкните по свойству onActivate, чтобы создать такой обработчик этого события: procedure TFormI.FormActivate(Sender: TObject); Begin TDemo:= ThreadDemo.Create (False), End; Вот так просто запускается дополнительный поток - мы инициируем объект TDemo, передавая в его Консруктор ThreadDemo.Create единственный параметр False (этот параметр показывает, должен ли вновь созданный поток “спать” - True или он обязан немедленно начать работу - False). Программа в любой момент может приостановить работу потока, присвоив его свойству suspended значение True, и продолжить его выполнение, присвоив этому свойству значение False. Обратите внимание - метод Execute потока вынесен в секцию protected и поэтому недоступен из основного модуля. Выполнение этого метода начинается автоматически, как только свойство suspended примет значение False. Для обращения к свойствам и методам визуальных компонентов формы Form1 предназначен специальный метод потока Synchronize. Единственным параметром обращения к этому методу должно быть имя любой потоковой процедуры без параметров. Внутри такой процедуры разрешается обращаться к методам и свойствам визуальных компонентов. В нашем потоке две такие процедуры - UрdateMemo и updateGuage. В первой строка s добавляется к содержимому редактора mmoutput, во втором - глобальная переменная n присваивается свойству progress индикатора Gauge1. Поскольку эти процедуры не могут иметь параметров, для управления их работой приходится использовать глобальные переменные S и N.
В Object Pascal допускается использование типизированных констант. Они задаются в разделе объявления констант следующим образом: <идентификатор>: <тип> = <значение> Здесь <идентификатор> - идентификатор константы; <тип> - тип константы; <значение> - значение константы. Во всех версиях Delphi, кроме версии 6, типизированным константам можно присваивать другие значения в ходе выполнения программы, поэтому фактически они представляют собой переменные с начальными значениями, т. е. являются инициированными переменными. Типизированная константа приобретает указанное в ее объявлении значение, т. е. инициируется, лишь один раз: к моменту начала работы программы. При повторном входе в блок (процедуру или функцию), в котором она объявлена, инициация типизированной константы не производится, и она сохраняет то значение, которое имела к моменту выхода из блока. Типизированные константы могут быть любого типа, кроме вариантов, файлов, объектов и классов. Нельзя также объявить типизированную константу-запись, если хотя бы одно из ее полей является полем файлового типа, вариантом, объектом или классом. Типизированную константу нельзя использовать в качестве значения при объявлении других констант или границ типа-диапазона.
|