Потоки в Delphi

Организация многопоточной работы в Delphi




Уроки Delphi
  1.  Первая программа
  2.  Использование компонентов
  3.  События Delphi
  4.  Типы данных Delphi
  5.  Создание своих типов данных
  6.  Выражения и операторы
  7.  Работа с файлами в Delphi
  8.  Дополнительные формы
  9.  Подпрограммы в Delphi
  10. Исключительные ситуации
  11. Взаимодействие приложения с пользователем
  12. Указатели в Delphi
  13. Обзор компонентов
  14. Работа со строками
  15. Создание интерфейса
  16. Графика в Delphi
  17. Многопоточность в Delphi
  18. Динамическое создание
        компонентов
Поиск по сайту




 Это важно:
   Метод Application.ProcessMessages;

 Это полезно:
   Параметр Sender в обработчиках событий;










Бояться не надо



   Потоки в Delphi выполняют функцию имитации псевдопараллельной работы приложения. Как известно, для организации многозадачности операционная система выделяет каждому приложению, выполняющемуся в настоящий момент, определённые кванты времени, длина и количество которых определяется его приоритетом. Поэтому объём работы, который приложение может выполнить, определяется тем, сколько таких квантов оно сможет получить в единицу времени. Для операционной системы каждый поток является самостоятельной задачей, которой выделяются кванты времени на общих основаниях. Поэтому приложение Delphi, умеющее создать несколько потоков, получит больше времени операционной системы, и соответственно сможет выполнить больший объём работы.

   Создать дополнительный поток в Delphi поможет объект TThread. Ввести объект TThread в программу можно двумя способами:

  1. с помощью Мастера;
  2. вручную.
   1. Мастер создания дополнительного потока в Delphi создаёт отдельный модуль, в рамках которого выполняется поток. Выполним:

   File -> New -> Other...

В появившейся табличке выбора найдём TThread Object. Появится окошко, в верхнюю строку которого (Class Name) введём имя нашего будущего потока: MyThread. В результате будет создан модуль, содержащий заготовку кода, реализующего дополнительный поток Delphi:
unit Unit2; // Имя модуля, содержащего поток. При сохранении его можно изменить.

interface

uses
  Classes;

type
  MyThread = class(TThread) //MyThread - заданное нами имя потока.
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

implementation

{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure MyThread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ MyThread }


procedure MyThread.Execute;
begin
  { Place thread code here }
end;

end.

   2. В первом способе класс MyThread был создан мастером в дополнительном модуле. Второй способ состоит в том, что мы сами создаём такой класс в рамках одного из уже существующих модулей программы, например, в модуле Unit1:

unit Unit1; //Обычный модуль в котором описывается основная программа

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

//Здесь необходимо описать класс TMyThread:
  TMyThread = class(TThread)
    private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

var
  Form1: TForm1;
//Нужно ввести переменную класса TMyThread
  MyThread: TMyThread;

implementation

{$R *.dfm}

//Нужно создать процедуру Execute, уже описанную в классе TMyThread
procedure TMyThread.Execute;
begin
//Здесь описывается код, который будет выполняться в потоке
end;


   Если поток создаётся мастером, т.е. в другом модуле, то не забудьте в основном модуле описать переменную - экземпляр потока, как указано выше. Также, поскольку класс потока описан в другом модуле, имя этого модуля необходимо добавить в секцию uses. Теперь можно запускать поток, даже если в его процедуре Execute нет ни единого оператора.

//Запускать поток будем нажатием на кнопку:
procedure TForm1.Button1Click(Sender: TObject);
begin
//Вначале нужно создать экземпляр потока:
  MyThread:=TMyThread.Create(False);
//Параметр False запускает поток сразу после создания, True - запуск впоследствии , методом Resume
//Далее можно указать параметры потока, например приоритет:
  MyThread.Priority:=tpNormal;
end;

end.

Применение потоков

  Если в основной программе попробовать выполнить такой цикл:

   while True do;

то приложение зависнет. А теперь поместите его в процедуру Execute. При нажатии на кнопку наш бесконечный цикл будет непрерывно выполняться в потоке, однако и приложение как целое не зависнет.

   В предыдущем примере поток выполняет бесконечный цикл. Однако, поток также обладает возможностями, позволяющими из основной программы передать ему приказ прекратить работу. Метод потока Terminate устанавливает свойство Terminated потока в True. Анализируя это свойство, поток может понять, что он должен завершить работу. Пример:

procedure TMyThread.Execute;
begin
  while True do
    if MyThread.Teminated then break;
end;

   Этот код выполняет бесконечный цикл. Однако, при выполнении в основной программе оператора

  MyThread.Terminate;

цикл завершается, и поток прекращает свою работу.

   При работе с потоками необходимо учитывать приоритет создаваемых потоков. Так, если в предыдущем примере запустить не один поток, а два или больше, нажав на кнопку несколько раз, то компьютер станет очень заметно "тормозить". Это происходит потому, что приоритет по умолчанию новых потоков - нормальный. Можно уменьшить его, задав

MyThread.Priority:=tpLower;

Этого достаточно, чтобы компьютер чувствовал себя более свободно. Вот таблица приоритетов:

Приоритет Описание
tpIdle Низший приоритет. Поток получает время только тогда, когда операционая система находится в состоянии простоя.
tpLowest Приоритет на два пункта ниже нормального
tpLower Приоритет на один пункт ниже нормального
tpNormal Нормальный приоритет
tpHigher Приоритет на один пункт выше нормального
tpHighest Приоритет на два пункта выше нормального
tpTimeCritical Максимальный приоритет. Приоритет на уровне функций ядра операционной системы.


Вот вам готовый проект работы c потоками, для экспериментов.

   В продолжение темы нужно рассмотреть

Особености взаимодействия потоков с объектами VCL

   Дело в том, что при работе с несколькими потоками в приложении необходимо гарантировать, что в данный момент только один из потоков может иметь доступ к свойствам и методам объекта VCL - визуального компонента Delphi. Для обеспечения этого условия в Delphi имеется специальный метод, в рамках которого и нужно вызывать процедуры, модифицирующие свойства и использующие методы визуальных компонентов. читать далее...


Графика в Delphi           В начало урока          Следующий урок  

Уроки Delphi начинающим



Вопросы и комментарии (35)      Решение задач в Delphi

Оставить комментарий:

Имя  

Текст комментария