DELPHISOURCE
| Домой | Статьи | Книги | FAQ | Компоненты | Программы |
| Архив сайта | Реклама на сайте | Ссылки | Связь |
Первые шаги с TThread в Delphi
Введение
Вне зависимости от того, хотим мы этого или нет, но прогресс движется дальше, появляются все новые технологии, новые процессоры, новые "высоты" производительности. В связи с этим, все чаще программистам приходится разрабатывать программы, которые используют сложные операции, в которых важна скорость и которые выполнялись бы одновременно с другими. Этому вопросу как раз и посвящена данная статья - создание многопоточных приложений (со множеством дочерних процессов, которые выполняются одновременно).
Зачем нужен Thread
Итак, зачем же нужен класс Thread и его потомки? Во-первых, этот объект позволяет создавать как бы несколько программ в одной (несколько процессов, или, потоков). Во-вторых, эти процессы могут выполняться как по очереди, так и одновременно (как запрограммирует разработчик). В-третьих, из этих процессов можно легко получить доступ ко всем глобальным данным программы, т.к. класс процесса является, по сути, просто частью программы - обычным юнитом (unit). В-четвертых, можно создать своих собственных потомков TThread и запустить сразу несколько экземпляров одного и того же созданного класса. В-пятых, каждым процессом очень легко управлять - запускать, завершать, приостанавливать, прерывать, устанавливать приоритетность, и т.д.
Краткое описание класса TThread
Итак, рассмотрим некоторые свойства, методы и события класса TThread.
|
Свойства |
Методы |
События | ||
|
FreeOnTerminate - освобождать ли память,
выделенную под экземпляр класса процесса, когда этот процесс
завершается. Если True - при завершении процесса (или при
вызове метода Terminate) экземпляр класса автоматически
освобождается (аналогично вызову метода Free). Тип:
Boolean; |
Create(CreateSuspended: Boolean) - создает
экземпляр класса. Параметр CreateSuspended указывает на то,
нужно ли создавать приостановленную задачу (True), или
запускать ее сразу
(False); |
OnTerminate - возникает, когда процесс находится в стадии завершения. |
Приоритет процесса
Итак, что же такое приоритет? Приоритет - это величина, определяющая, насколько данный процесс должен выполнятся быстрее по сравнению с другими. Т.е., другими словами, чем выше приоритет процесса, тем больше времени он отбирает у системы и других, параллельно работающих процессов. Далее разберем возможные значения свойства Priority класса TThread в порядке возрастания приоритета:
tpIdle - процесс выполняется только тогда, когда система не занята и больше нет работающих в данных момент процессов;
tpLowest - на два пункта ниже нормального;
tpLower - на один пункт ниже нормального;
tpNormal - нормальный. Такой приоритет у большинства задач;
tpHigher - на один пункт выше нормального;
tpHighest - на два пункта выше нормального;
tpTimeCritical - самый высокий приоритет - занимает все время процессора и системы. Это приоритет для систем реального времени, для которых важна каждая секунда и даже малейшая задержка может привести к сбою. Будьте осторожны с этим приоритетом!
Практика и примеры
Приведем небольшой пример того, как можно создать отдельный процесс:
|
Пример 1. "Шаблон" для создания Thread-ов. |
{Определение класса TMyThread}
type
TMyThread = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
implementation
procedure TMyThread.Execute;
begin
{Если Вы хотите, чтобы процедура DoWork выполнялась лишь один раз - удалите цикл while}
while not Terminated do
Synchronize(DoWork);
end;
procedure TMyThread.DoWork;
begin
{Здесь можно уже выполнять те задачи, которые должны быть исполнены процессом}
end;
|
А теперь - замечательный пример для изучения Thread! В нижеследующем примере приложение создает два параллельно работающих процесса. Один Thread пытается установить флажок CheckBox1 в положение "включено" (Checked := True), а другой, передергивая первого - в "выключено".
|
Пример 2. "Поединок" Thread-ов :-). |
{В форму Form1 нужно поместить TCheckBox - CheckBox1
и одну кнопку TButton - Button1}
{Определение классов двух Thread-ов}
type
TMyThread1 = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
TMyThread2 = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
var Form1: TForm1;
T1 : TMyThread1;
T2 : TMyThread2;
implementation
procedure TMyThread1.Execute;
begin
{Пока процесс не прервали, выполняем DoWork}
while not Terminated do
Synchronize(DoWork);
end;
procedure TMyThread2.Execute;
begin
{Пока процесс не прервали, выполняем DoWork}
while not Terminated do
Synchronize(DoWork);
end;
procedure TMyThread1.DoWork;
begin
{Пытаемся победить второй процесс :-)}
Form1.CheckBox1.Checked := True;
end;
procedure TMyThread2.DoWork;
begin
{Пытаемся победить первый процесс :-)}
Form1.CheckBox1.Checked := False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
{Если кнопка называется Stop...}
if Button1.Caption = 'Stop' then begin
{Прерываем оба процесса}
T1.Terminate;
T2.Terminate;
{Изменяем название кнопки}
Button1.Caption := 'Start';
{Выходим из процедуры}
Exit;
end;
{Создаем и сразу запускаем два процесса}
T1 := TMyThread1.Create(False);
T2 := TMyThread2.Create(False);
{Здесь можно поэкспериментировать с приоритетами:
T1.Priority := tpLowest;
T2.Priority := tpHighest;
}
{Переименовываем кнопку}
Button1.Caption := 'Stop';
end;
|
P.S. Отличный пример работы с TThread можно найти в подкаталоге Demos\Threads каталога, куда Вы установили Borland Delphi.
Эпилог
В этой статье отображены основные стороны работы с процессами (потоками) Thread в Borland Delphi. Если у Вас есть вопросы - скидывайте их мне на E-mail: snick@mailru.com, а еще лучше - пишите в конференции этого сайта (Delphi. Общие вопросы), чтобы и другие пользователи смогли увидеть Ваш вопрос и попытаться на него ответить!
| Delphisource (2006г.) |