|
#1
|
|||
|
|||
Работа с потоками
Как сделать правильно поток, если действие которое нужно выполнить имеет еще параметры которые заполняются во время работы. Вот пример:
Дан код: Код:
{Проверка на наличие CD\DVD} function DiskInDrive(ADriveLetter:Char):Boolean; var SectorsPerCluster,BytesPerSector,NumberOfFreeClusters,TotalNumberOfClusters:Cardinal; begin Result:=GetDiskFreeSpace(PChar(ADriveLetter+':\'),SectorsPerCluster,BytesPerSector,NumberOfFreeClusters,TotalNumberOfClusters); end; |
#2
|
||||
|
||||
Вариант в лоб (кривой и неправильный): сделать букву полем класса-наследника TThread, в потоке читать его и передавать в описанную функцию. Учитывая, что поток переменную только читает, а основной код только пишет, работать будет, только иногда с неактуальными данными.
Вариант нормальный, правильный, по фень-шую: то же самое, что и первый, только + критические секции. Подробности - в гугле. jmp $ ; Happy End! The Cake Is A Lie. |
#3
|
||||
|
||||
А что мешает в поток засунуть и обход всех дисков? Как я понял это последовательная операция и вы ее не планируете разбивать на отдельные потоки для каждого из дисков.
Жизнь такова какова она есть и больше никакова. Помогаю за спасибо. |
#4
|
|||
|
|||
Цитата:
|
#5
|
||||
|
||||
Цитата:
Код:
{ Some applications need to know when the user inserts or removes a compact disc or DVD from a CD-ROM drive without polling for media changes. Windows provide a way to notify these applications through the WM_DEVICECHANGE message. } type TForm1 = class(TForm) private procedure WMDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE; public end; {...} implementation {$R *.DFM} procedure TForm1.WMDeviceChange(var Msg: TMessage); const DBT_DEVICEARRIVAL = $8000; // system detected a new device DBT_DEVICEREMOVECOMPLETE = $8004; // device is gone var myMsg: string; begin inherited; case Msg.wParam of DBT_DEVICEARRIVAL: myMsg := 'CD inserted!'; DBT_DEVICEREMOVECOMPLETE: myMsg := 'CD removed!'; end; ShowMessage(myMsg); end; Код:
// Advanced Code: // When the device is of type volume, then we can get some device specific // information, namely specific information about a logical volume. // by Juergen Kantz unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; label1: TLabel; private procedure WMDeviceChange(var Msg: TMessage); message WM_DeviceChange; { Private declarations } public { Public declarations } end; const DBT_DeviceArrival = $8000; DBT_DeviceRemoveComplete = $8004; DBTF_Media = $0001; DBT_DevTyp_Volume = $0002; type PDevBroadcastHdr = ^TDevBroadcastHdr; TDevBroadcastHdr = packed record dbcd_size: DWORD; dbcd_devicetype: DWORD; dbcd_reserved: DWORD; end; type PDevBroadcastVolume = ^TDevBroadcastVolume; TDevBroadcastVolume = packed record dbcv_size: DWORD; dbcv_devicetype: DWORD; dbcv_reserved: DWORD; dbcv_unitmask: DWORD; dbcv_flags: Word; end; var Form1: TForm1; implementation {$R *.dfm} function GetDrive(pDBVol: PDevBroadcastVolume): string; var i: Byte; Maske: DWORD; begin if (pDBVol^.dbcv_flags and DBTF_Media) = DBTF_Media then begin Maske := pDBVol^.dbcv_unitmask; for i := 0 to 25 do begin if (Maske and 1) = 1 then Result := Char(i + Ord('A')) + ':'; Maske := Maske shr 1; end; end; end; procedure TForm1.WMDeviceChange(var Msg: TMessage); var Drive: string; begin case Msg.wParam of DBT_DeviceArrival: if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = DBT_DevTyp_Volume then begin Drive := GetDrive(PDevBroadcastVolume(Msg.lParam)); label1.Caption := 'CD inserted in Drive ' + Drive; end; DBT_DeviceRemoveComplete: if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = DBT_DevTyp_Volume then begin Drive := GetDrive(PDevBroadcastVolume(Msg.lParam)); label1.Caption := 'CD removed from Drive ' + Drive; end; end; end; end. Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
#6
|
|||
|
|||
Вот мой код из одного из проектов. Довит появление/удаление диска (работает на CD/DVD и флешках, проверял):
Код:
procedure TBrowserMainForm.WMDeviceChange(var Message: TMessage); const DBT_CONFIGCHANGECANCELED = $19; DBT_CONFIGCHANGED = $18; DBT_CUSTOMEVENT = $8006; DBT_DEVICEARRIVAL = $8000; DBT_DEVICEQUERYREMOVE = $8001; DBT_DEVICEQUERYREMOVEFAILED = $8002; DBT_DEVICEREMOVECOMPLETE = $8004; DBT_DEVICEREMOVEPENDING = $8003; DBT_DEVICETYPESPECIFIC = $8005; DBT_DEVNODES_CHANGED = $7; DBT_QUERYCHANGECONFIG = $17; DBT_USERDEFINED = $FFFF; var ASelFolder : String; begin If FDevChanged Then Begin ASelFolder := tvFolders.Path; tvFolders.Items.BeginUpdate; tvFolders.Refresh(tvFolders.Items[0]); tvFolders.Path := ASelFolder; tvFolders.Items.EndUpdate; FDevChanged := False; End; Case Message.WParam Of DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE : Begin CreateDiskShortCuts; FDevChanged := True; End; End; end; |
#7
|
|||
|
|||
Цитата:
Вот опять куда вы полезли, я про потоки вы тут про определение, мне нужно загнать процедуру в поток, не важно как она определяет вставлен ли диск или нет. |
#8
|
||||
|
||||
обертка переменной критической секцией поможет. либо критическая секция в get'тере / set'тере.
Пишу программы за еду. __________________ |
#9
|
||||
|
||||
Цитата:
Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
#10
|
|||
|
|||
Цитата:
Хорошо, тогда скажите как не отображать букву диска если если там нет диска, моя программа в любом случаи определяет даже если там нет диска, букву привода. |