Разработка многопоточных задач в среде delphi
Многопоточность используется для: - обхода медленных процессов. Когда используется только один поток, приложение может приостановить свое выполнение на то время, пока им завершается какой-либо медленный процесс (доступ к диску, связь с другим компьютером по сети и т. д.). Центральный процессор компьютера в данный момент находится в режиме ожидания и практически не выполняет никаких команд. С использованием многопоточности приложение может продолжать выполнение других потоков, пока один из потоков ожидает завершение медленного процесса; - организации поведения приложения. Благодаря использованию потоков, можно для каждой задачи приложения (если каждой задаче выделен свой поток) распределить приоритеты выполнения. Задача, имеющая наибольший приоритет, будет занимать больше процессорного времени, что очень важно для решения критических задач; - поддержки мультипроцессорной обработки. Если в компьютере, на котором запущено многопоточное приложение, имеется несколько процессоров, то можно значительно увеличить скорость выполнения приложения, направляя на каждый процессор свой поток.
|
Пример создания многопоточного приложения в Delphi
Задача: создать простое приложение, состоящее из трех потоков.
В главном меню выбрать пункт File/New Application.
Р
Добавить новый объект потока через пункт главного меню Delphi File/New/Other->Thread Object. В открывшемся диалоговом окне ввести имя для нового потомка класса TThread, например TmyThread1. Delphi автоматически добавит модуль Unit2 в приложение.В этом модуле появится заготовка
unit Unit2;
interface
uses
Classes;
type
TMyThread1 = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override; //метод класса абстрактный,поэтому override
end;
implementation
{ TMyThread1 }
procedure TMyThread1.Execute;
begin
{ Place thread code here }
end;
end.
В раздел public добавить глобальную переменную count. В результате должно получиться следующее:
type
TMyThread1 = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
public // добавлено
count:integer; // добавлено
end;
Записать в метод Execute код, который должен выполняться в потоке. Пусть это будет код, который генерирует случайные числа и присваивает их глобальной переменной count. Для того чтобы генерация случайных чисел была бесконечной, зациклим ее с помощью так называемого "бесконечного цикла":
procedure TMyThreadl.Execute; begin while true do begin count:=random(maxint); end; end;
Создать второй объект потока, который должен заполнять индикатор хода работы (Progress Bar). По аналогии с первым объектом потока, при помощи главного меню Delphi создать объект потока с именем TMyThread2. Во вновь добавленном модуле Unit3 определить глобальную переменную prcount:
type TMyThread2 = class(TThread) private { Private declarations } protected procedure Execute; override; public // добавлено prcount:integer; // добавлено end;
В процедуре Execute объекта TMyThread2 записать следующий код, также зациклив его:
procedure TMyThread2.Execute; begin
while true do begin prcount:=prcount+l; if prcount>100 then prcount:=0; end; end;
Сохранить проект Project1 и модули Unit1, Unit2, Unit3.
Добавить в модуле Unit1 в описание класса формы в разделе private объекты потоков Thread1 - потомок класса TmyThreadl1и Thread2 - потомок класса TMyThread2:
type TForml = class(TForm) ProgressBarl: TProgressBar; Editl: TEdit; Timerl: TTimer; procedure FormCreate(Sender: TObject); private Threadl:TMyThreadl; // добавлено Thread2:TMyThread2; // добавлено public { Public declarations } end;
Дважды щелкнуть на любом свободном пространстве формы Form1. При этом откроется "заготовка" для метода создания формы FormCreate формы Form1. В обработчике FormCreate ввести код:
procedure TForml.FormCreate(Sender: TObject); begin Thread1:=TmyThread1.Create(False); // конструктор Thread1.priority:=tpLowest; // установка приоритета потока (см. ниже) Thread2:=TMyThread2.Create(False); // конструктор Thread2.priority:=tpNormal; // установка приоритета потока end;
Параметр, который передается в методе Create класса TThread- CreateSuspended. Данный параметр может принимать логическое значение истина или ложь (true, false). Этот параметр показывает, создавать поток в приостановленном состоянии (true) или запускать его сразу же (false). То есть метод Execute будет вызван автоматически сразу, если параметр CreateSuspended равен false.
Приоритеты указывают операционной системе, сколько процессорного времени выделяется для данного потока. Для критических задач можно установить наивысший приоритет, для менее значимых - более низкий приоритет. Приоритет каждого потока складывается из двух составляющих:
-класса приоритета - приоритета процесса, породившего поток;
- относительного приоритета - приоритета самого потока. Класс приоритета процесса может принимать одно из четырех значений: Idle, Normal, High и Realtime, которые выражаются числовыми значениями от 4 до 24. По умолчанию, любое приложение получает приоритет Normal. Процессов (в примере используется этот приоритет).
Классы приоритетов процессов
Значение класса |
Приоритет |
Числовое значение |
Idle |
Низший приоритет для выполнения фоновых задач |
4 |
Normal |
Стандартный приоритет, который имеют большинство приложений Windows |
7-9 |
High |
Приоритет высокого уровня, приложение получает больше процессорного времени, чем имеющее класс Normal |
13 |
Realtime |
Наивысший уровень приоритета |
24 |
Для определения текущего и установки требуемого класса приоритета используются функции GetPrioriryClass и SetPriorityClass соответственно. Для установки высокого класса приоритета (High) можно, например, использовать следующий код: If not SetPriorityClass(GetCurrentProcess, HIGH_PRIORITY_CLASS) then ShowMessage ('Ошибка установки класса приоритета'); По возможности следует избегать установки классов приоритетов High и Realtime, т. к. поток приложения может получить больше процессорного времени, чем сама операционная система, что может привести к серьезным проблемам. Для установки значения относительного приоритета у потоков имеется свойство Priority, которое может принимать семь значений.