Особенности разработки потоковDelphi , Компоненты и Классы , ПотокиСовременные операционные системы Windows 32 обеспечивают не только многозадачность, т. е. возможность параллельной работы нескольких программ, но и многопоточность, когда в рамках одной программы организуется несколько параллельно выполняемых фрагментов (потоков), каждый из которых конкурирует с другими потоками за наиболее важный ресурс - время центрального процессора. В многопоточном режиме время ЦП выделяется для каждого процесса небольшими порциями (квантами), по истечении этого времени управление передается другому потоку и т. д. до тех пор, пока потоки не закончат свою работу. В любой работающей программе организуется как минимум один поток для команд программы. С помощью объектов класса TThread программа может создать дополнительные потоки для проведения некоторой фоновой работы (например, текстовый процессор Word создает дополнительные потоки для проверки правильности орфографии, разбивки на страницы, печати документа и т. п.). Для создания дополнительного потока в программах Delphi предназначен специальный модуль потока в репозитории он обозначен пиктограммой Thread Obiecll). При выборе этого модуля Delphi запрашивает имя класса, который будет дочерним для основополагающего класса TThread. Необходимость наследования связана с тем, что класс TThread содержит абстрактный метод Execute, который, собственно, и должен исполняться в рамках нового потока и который, следовательно, обязан перекрываться в потомках. После указания имени дочернего класса Delphi раскрывает дополнительный модуль с обширным комментарием и заготовкой для дочернего класса. Например (с соответствующим переводом): unit Unit1; 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 TForm1.Button1Click(Sender: TObject); begin if Tag = 0 then begin SpinEditl.Text := Float - ToStr(sqr(StrToPloat(SpinEditl.Text))); if StrToFloat(SpinEditl.Text) > 1 el233 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 TForm1.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. Разработка потоков в Delphi: создание дополнительных потоков, использование метода Synchronize, пример программы для непрерывного обновления содержимого многострочного редактора и выполнения математических вычислений. Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |