На этом шаге мы рассмотрим пример программы,
демонстрирующей опрос устройства с помощью потока.
Используя поток, мы сможем заставить нашу программу реагировать на подключение дискового устройства. При тестировании приложения в качестве дискового устройства использовался флэш-накопитель.
На форму следует поместить компоненты 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. Также стоит обратить внимание на то, что цикл, выполняемый в потоке, будет работать до момента уничтожения потока, поэтому программа среагирует и на отключение того же дискового устройства, что было подключено нами после запуска потока.
На этом мы закончим краткое изложение организации и использования потоков.