Шаг 8.
Организация потоков в Delphi-приложениях.
Пример: опрос устройства

    На этом шаге мы рассмотрим пример программы, демонстрирующей опрос устройства с помощью потока.

    Используя поток, мы сможем заставить нашу программу реагировать на подключение дискового устройства. При тестировании приложения в качестве дискового устройства использовался флэш-накопитель.

    На форму следует поместить компоненты TLabel и TButton. Вид формы представлен на рис. 1.


Рис.1. Вид формы приложения

    После запуска программа считает количество имеющихся на компьютере дисковых носителей. При нажатии кнопки "Пуск" запускается поток, который введет опрос следующего по счету дискового устройства. Когда устройство будет подключено, в компонент TLabel будет выведено соответствующее сообщение.

    Проект приложения содержит два модуля. Текст модуля Unit1.

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    PortThread: TPortThread;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  hdevice: THandle; //дескриптор устройства
  devcount: byte; //счетчик устройств


implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  PortThread:=TPortThread.Create(false);
  PortThread.FreeOnTerminate:=True;
  PortThread.Priority:=tpIdle;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if PortThread<>nil
  then
    PortThread.Terminate;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  devcount:=0;
  while hdevice<>INVALID_HANDLE_VALUE do
  begin
    //производим опрос устройства
    hdevice:=CreateFile(PChar('\\.\PHYSICALDRIVE'+inttostr(devcount)),
                       0,
                       0,
                       nil,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       0);
    if hdevice<>INVALID_HANDLE_VALUE
    then
      inc(devcount);
  end;
end;

end.

    Текст модуля Unit2.

unit Unit2;

interface

uses
  Classes,Windows,SysUtils;

type
  TPortThread = class(TThread)
  private
    { Private declarations }
    hdevice: THandle;
  protected
    procedure Execute; override;
    procedure LabelOn;
    procedure LabelOff;
  end;

implementation

uses unit1;


{ TPortThread }

procedure TPortThread.Execute;
begin
  { Place thread code here }
  while not terminated do
  begin
    hdevice:=CreateFile(PChar('\\.\PHYSICALDRIVE'+inttostr(devcount)),
                       0,
                       0,
                       nil,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       0);
    if hdevice=INVALID_HANDLE_VALUE
    then Synchronize(LabelOff)
    else Synchronize(LabelOn);
    sleep(1000);
  end;
end;

procedure TPortThread.LabelOn;
begin
  Form1.Label1.Caption:='Устройство подключено';
end;

procedure TPortThread.LabelOff;
begin
  Form1.Label1.Caption:='Подключите устройство';
end;

end.

    Текст этого примера можно взять здесь.

    К приведенному выше описанию принципа работы программы можно добавить лишь то, что проверка наличия дискового устройства осуществляется с помощью функции Windows API CreateFile, которая при существовании дискового устройства с заданным индексом (в нашей программе он определяется переменной devcount) возвращает дискриптор данного устройства, в противном случае возвращает значение INVALID_HANDLE_VALUE. Также стоит обратить внимание на то, что цикл, выполняемый в потоке, будет работать до момента уничтожения потока, поэтому программа среагирует и на отключение того же дискового устройства, что было подключено нами после запуска потока.

    На этом мы закончим краткое изложение организации и использования потоков.




Предыдущий шаг Содержание