Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / Pascal и Delphi / Иллюстрированный самоучитель по Delphi 6 / Часть II . Язык Object Pascal /
8  Perl
8  PHP
8  JavaScript
8  HTML
8  DHTML
8  XML
8  CSS
8  C / C++
8  Pascal и Delphi
8  Турбо Ассемблер
8  MySQL
8  CASE-технологии
8  Алгоритмы
8  Python
8  Обратная связь
8  Гостевая книга
Новости о мире


Особенности разработки модулей-потоков - Программирование от RIN.RU
Особенности разработки модулей-потоков

Современные операционные системы 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) > 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 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.



 8  Комментарии к статье  8  Обсудить в форуме  8  Обсудить в чате

 
  
  
    Copyright ©  RIN 2003 - 2004      * Обратная связь