Иллюстрированный самоучитель по Delphi 7 для профессионалов

Пример создания многопоточного приложения в Delphi

  1. Код, вносимый в метод Execute, вычисляет число я, используя сходимость бесконечного ряда Лейбница:
Pi = 4-4/3 + 4/5-4/7 + 4/9 – …

Разумеется, отображать новое значение после каждой итерации – это то же самое, что стрелять из пушки по воробьям. На отображение информации система потратит в десятки раз больше времени, чем на собственно вычисления. Поэтому мы ввели константу updatePeriod, которая регулирует периодичность отображения текущего значения.

Код метода Execute показан ниже:

const
// Лучше использовать нечетное число для того, чтобы избежать эффекта
// мерцания UpdatePeriod = 1000001;
procedure TPiThread.Execute; var sign: Integer;
PiValue, PrevValue: Extended; i: Int64;
begin
{ Place thread code here } PiValue: = 4; sign: = -1; i: = 0; repeat Inc(i);
PrevValue: = PiValue;
PiValue: = PiValue + sign * 4 / (2*i+l); sign: = -sign;
if i mod UpdatePeriod = 0 then
begin
GlobalPi: = PiValue; GlobalCounter: = i; Synchronize(fmMain.UpdatePi);
end;
until Terminated or (Abs(PiValue – PrevValue)<1E-19);
end;
  1. Откройте меню File и выберите пункт Save As. Сохраните модуль с потоком как uPiThread.pas.
  2. Отредактируйте главный файл модуля uMain.pas и добавьте модуль uPiThread к списку используемых модулей в секции интерфейса. Он должен выглядеть так:
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, StdCTRLs, uPiThread;
  1. В секции public формы TfmMain добавьте ссылку на создаваемую нить:
PiThread: TPiThread;
  1. Добавьте в модуль uMain две глобальные переменные
GlobalPi: Extended;
GlobalCounter: Int64;

…и метод UpdatePi:

procedure TfmMain.UpdatePi;
begin
if Islconic(Application.Handle) then
Exit;
LaValue.Caption: = FloatToStrF(GlobalPi, ffFixed, 18, 18);
lALTerNum.Caption: = IntToStr(GlobalCounter) + ' iterations';
end;

Этот метод, если вы обратили внимание, вызывается из потока посредством процедуры Synchronize. Он отображает текущее значение приближения к числу "пи" и количество итераций.

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

  1. Выполните двойной щелчок на свободном месте рабочей области формы, при этом создастся шаблон метода FormCreate. Здесь мы отобразим значение системной константы р±:
procedure TfmMain.FormCreate(Sender: TObject);
begin
laBuiltln.Caption: = FloatToStrF(Pi, ffFixed, 18, 18);
 end;
  1. Выберите на форме переключатель (его название cbcalcuiate) и назначьте событию Onclick код, создающий и уничтожающий вычислительный поток в зависимости от состояния переключателя:
procedure TfmMain.cbCalculateClick(Sender: TObject);
begin if cbCalculate.Checked then
begin
PiThread: = TPiThread.Create(True);
PiThread.FreeOnTerminate: = True;
PiThread.Priority: = tpLower;
PiThread.Resume; end else begin
if Assigned(PiThread) then PiThread.Terminate;
end;
end;

Таким образом, многопоточное приложение готово к запуску. Если все пройдет нормально, вы увидите картинку, подобную той, которая приведена на рис. 29.5.

Иллюстрированный самоучитель по Delphi 7 для профессионалов › Потоки и процессы › Пример создания многопоточного приложения в Delphi
Рис. 29.5. Выполняющееся приложение Threads1

Пока один из авторов писал текст этого раздела, запущенное одновременно приложение Threads1 выполнило пять миллиардов итераций и приблизилось к встроенному значению Pi в десятом разряде. Интересно, насколько хватит терпения у вас?

Этот простой пример – первый шаг в усвоении того, как от базового класса rrhread можно порождать собственные классы. Из-за своей простоты он не лишен недостатков; более того – если бы вычислительных нитей было не одна, а более, кое-какие приемы были бы даже ошибочными. Но – об этом ниже.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.