Nisam imao ranije iskustva sa Thread-ovima, pa me interesuje par stvari oko funkcionisanja.
Napravio sam u zasebnom fajlu Thread koji uzima podatke iz TSQLQuery-a i smešta ih u lokalnu TCombox, i nakon izvršenja uz proceduru Synchronize prenosi podatke u TComboBox na određenoj formi.
unit ThreadS;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, sqldb, db,StdCtrls,Forms,Controls;
type
{TGetComboItems}
TGetComboItems = class(TThread)
public
IsFinish : Boolean;
constructor Create(sSQL,sField,sFieldID: String;
ComboBox:TComboBox; sIndex: Integer);
destructor Destroy; override;
protected
S: String;
tQry: TSQLQuery;
tSQL: String;
tCombo,Combo: TComboBox;
tField: String;
tFieldID: String;
tIndex: Integer;
procedure Execute; override;
procedure AddToCombo;
procedure ShowStatus;
procedure SetCursorWait;
procedure SetCursorDefault;
end;
implementation
uses modul1,glava1s;
{ TGetComboItem }
constructor TGetComboItems.Create(sSQL, sField, sFieldID: String;
ComboBox: TComboBox; sIndex: Integer);
begin
FreeOnTerminate:=true;
tQry := TSQLQuery.Create(nil);
tQry.DataBase := modul.konekcija;
tQry.Transaction := modul.Transakcije;
tQry.SQL.Clear;
tQry.SQL.Add(sSQL);
tQry.Open;
tField:=sField;
tFieldID:=sFieldID;
tIndex:=sIndex;
tCombo:=ComboBox;
tCombo.Clear;
tCombo.Enabled:=false;
Combo:=TComboBox.Create(nil);
IsFinish:=false;
inherited Create(false);
end;
destructor TGetComboItems.Destroy;
begin
tQry.Free;
Combo.Free;
Synchronize(@SetCursorDefault);
inherited Destroy;
end;
procedure TGetComboItems.Execute;
begin
if not Terminated then
begin
Synchronize(@SetCursorWait);
s:='Učitavanje podataka je u toku...';
Synchronize(@ShowStatus);
with tQry do
Begin
while not eof do
begin
if (not IsFinish) then
begin
Combo.Items.AddObject(FieldByName(tField).AsString
,TObject(FieldByName(tFieldID).AsInteger));
Synchronize(@ShowStatus);
Next;
end
else
Last;
end;
Close;
end;
IsFinish:=true;
s:='Učitavanje podataka je izvršeno.';
Synchronize(@ShowStatus);
Synchronize(@AddToCombo);
end;
end;
procedure TGetComboItems.AddToCombo;
begin
tCombo.Items:=Combo.Items;
tCombo.ItemIndex:=tCombo.Items.IndexOfObject(TObject(tIndex));
tCombo.Enabled:=true;
end;
procedure TGetComboItems.ShowStatus;
begin
Form1.Status.SimpleText:=s;
end;
procedure TGetComboItems.SetCursorWait;
begin
Screen.Cursor:=crSQLWait;
end;
procedure TGetComboItems.SetCursorDefault;
begin
Screen.Cursor:=crDefault;
end;
end.
Thread pozivam na sledeći način:
procedure TForm1.firma_izmClick(Sender: TObject);
var
sFIRMA: PFirma;
GetMesta : TGetComboItems;
begin
// Učitavanje gradova i tekućih računa u ComboBox i indeksiranje
GetMesta:=TGetComboItems.Create('select * from tab_mesta','mesto','id', firma_mesto, sFIRMA^.ID_MESTA);
GetMesta.Start;
....
end;
1. Interesuje me, da li je potrebno i na koji način se vrši oslobađanje memorije od Thread-a, ili se on sam uništi nakon izvršenja, pošto sam pokušavao da pozovem FreeAndNil(GetMesta) nakon izvršenja al izbaci grešku.
Iz Thread-om punim Combo jer sam želeo da se prvo otvori forma i dozvole korekcije ostalih podataka dok se i combo ne učita, jer koristim MySql sa net servera pa se podaci malo sporije učitavaju, čisto da se ne gubi vreme na učitavanje.
2. Da li je potrebno osloboditi Objekte iz ComboBox-a posle korišćenja, il je dovoljno ComboBox.Clear, pošto je objekat tipa INTEGER, ne dozvoljava mi da izvršim Object.Free nad bilo kojim slogom.
3. I da li je OK način na koji sam to rešio.