![]() |
|
ListView Veri doldurma esnasında TTask kullanımı - Baskı Önizleme +- Delphi Can (https://www.delphican.com) +-- Forum: Delphi (https://www.delphican.com/forumdisplay.php?fid=3) +--- Forum: Mobil Platform - FireMonkey (FMX) (https://www.delphican.com/forumdisplay.php?fid=7) +--- Konu Başlığı: ListView Veri doldurma esnasında TTask kullanımı (/showthread.php?tid=5724) |
ListView Veri doldurma esnasında TTask kullanımı - kornakamil - 13-02-2021 küçük 3500- 4000 kayıtlık bir veritabanım var . Veritabanı bilgilerini ListViewe görsel olarak bağladım ve senkronize ettim . Veri sayısı küçük olduğu için senkronizasyon işlerimi kolaylaştırıyor. Problemim şu . Veritabanını Listviewe yüklerken TTask kullanıyorum . TTask içinde veritabanı bağlantısı kurulup Table açıldığında TTask sonlanıyor. Yükleme esnasında oluşturduğum Frame doğal olarak işlevini tamamlıyor. Verile Listviewe yüklenirken yaklaşık 30 saniye kadar verilerin gelmesini bekliyorum . Görsel olarak hoş olmuyor. Listview tüm veritabanıma yükleninceye TTask işlemimin devamını nasıl sağlıyabilirim . Tam olarak problemimi anlatabilmişimdir umarım . Yardımlarınız için şimdiden teşekkür ederim .. ListView Veri doldurma esnasında TTask kullanımı - kornakamil - 14-02-2021 Sanırım sorunun çözümünü FGX bileşeni sağlayacak. Abdullah hocam Sydney içinde tekrar paketleseniz bileşeni. İnternette ve sitede önerilen çözümleri deniyorum fakat istediğim akıcılıkta bir sonuç elde edemedim .. ListView Veri doldurma esnasında TTask kullanımı - mrmarman - 14-02-2021 Veritabanı bağlantısını görsel olarak kurup, ne kadar kontrolünüzde olduğunu bilemediğim ve ayrıca ttask içinde bu veri tabanı bağlantısını nasıl zapt ettiğinizi ve listview'e aktardığınızı bilemiyorum. Görsel bağlantı yerine kod ile veritabanına bağlanırsanız, (burada bunun üzerinde yorum yapılabilir) yazacağınız procedure ve callback yapıları size tthread aracılığıyla bu paralelleştirme imkanını kolaylaşır. ListView Veri doldurma esnasında TTask kullanımı - kornakamil - 14-02-2021 ListView verileri kodla doldurdum.. Veritabanı ilişkisinide Locate ile sağladım item seçildikçe . Yüklenme hızı 4-5 kat arttı . Ama Listview görüntülenmeden biraz kasılma hala var . . Kod yazarken kolaya kaçmamak lazım bunun önemini daha iyi gördüm . Hız olarak çok farketti . Yardımlarınız için teşekkür ederim ListView Veri doldurma esnasında TTask kullanımı - mrmarman - 14-02-2021 Şöyle bir örnek proje hazırladım sizin için.... Anlatılanlar ete kemiğe bürünsün diye örneklemek istedim. Hem başlığı okuyanlar da fiziki bir örnek elde etmiş olurlar. Örnek Proje RAR ile paketli bu mesaj ekindedir. ![]()
Thread işlemlerinde bağımsızlaştırılmış işlemler önemlidir. Bilgilendirme için kullanılan aNotif procedure de (bu örnekte gerek yoktu aslında dinamik procedure'ler değil de asıl projenizdeki diğer nesneler ile iletişim için Syncronize kullanımı önemli) Syncronize ile çağrıldı. Çok önemli not :
Uses System.IOUtils,
System.Notification,
Data.DB,
FireDAC.Stan.Intf,
FireDAC.Comp.UI,
FireDAC.FMXUI.Wait, {FDGUIxWaitCursor.Provider := 'FMX'}
FireDAC.DApt,
FireDAC.Comp.Client,
FireDAC.Stan.Param,
FireDAC.Stan.Def,
FireDAC.Stan.Async,
FireDAC.Phys.Intf,
FireDAC.Phys.SQLiteWrapper.Stat,
FireDAC.Phys.SQLite;
Var
FDGUIxWaitCursor : TFDGUIxWaitCursor;
FDPhysSQLiteDriverLink : TFDPhysSQLiteDriverLink;
FDGUIxAsyncExecuteDialog : TFDGUIxAsyncExecuteDialog;
FDBFileName : String;
procedure TForm1.DB_Prepare( dbName: String = 'dbSqlite.db' );
Var
LConnection : TFDConnection;
LQuery : TFDQuery;
LRes : TResourceStream;
begin
{$if Defined(MSWINDOWS)}
FDBFileName := System.IOUtils.TPath.Combine( TPath.Combine(GetCurrentDir, 'DATA'), dbName);
{$elseif Defined(ANDROID)}
FDBFileName := TPath.Combine( TPath.Combine( TPath.GetDocumentsPath, 'DATA'), dbname);
{$endif}
if NOT DirectoryExists ( ExtractFilePath(FDBFileName))
then ForceDirectories( ExtractFilePath(FDBFileName) );
aNotif( 'DB_Background', 'DB Path', FDBFileName );
if NOT FileExists( FDBFileName ) then
begin
LConnection := TFDConnection.Create( nil );
LConnection.Params.Values['DriverID'] := 'SQLite';
LConnection.Params.Values['database'] := FDBFileName;
LQuery := TFDQuery.Create( nil );
try
LQuery.Connection := LConnection;
LQuery.SQL.Text := ''
+ 'CREATE TABLE ''OrnekTable'' ('
+ ' ''id'' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,'
+ ' ''Ad'' varchar(255) default NULL,'
+ ' ''DogTar'' varchar(255),'
+ ' ''Adres'' varchar(255) default NULL,'
+ ' ''Telefon'' varchar(100) default NULL )'
;
try
LQuery.ExecSQL;
except
aNotif( 'DB_Background', 'DB Cretation', 'CREATE Edilemedi...' );
Exit;
end;
LRes := TResourceStream.Create( HInstance, 'SampleData', RT_RCDATA );
try
LQuery.SQL.LoadFromStream( LRes );
LQuery.ExecSQL;
finally
FreeAndNil(LRes);
end;
LConnection.Commit;
finally
FreeAndNil(LQuery);
FreeAndNil(LConnection);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DB_Prepare();
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
TThread.CreateAnonymousThread(procedure ()
var
LQuery : TFDQuery;
LConnection : TFDConnection;
begin
LConnection := TFDConnection.Create(nil);
LQuery := TFDQuery.Create( nil );
try
LQuery.Connection := LConnection;
LConnection.Params.Values['DriverID'] := 'SQLite';
LConnection.Params.Values['database'] := FDBFileName;
LQuery.SQL.Text := 'SELECT * FROM ''OrnekTable'' ';
LQuery.Active := True;
while NOT LQuery.Eof do
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
ListView1.Items.Add.Text := Format( '%s : %s', [ LQuery.FieldByName('Ad').AsString, LQuery.FieldByName('DogTar').AsString ] );
end);
LQuery.Next;
end;
LQuery.Active := False;
finally
FreeAndNil(LQuery);
FreeAndNil(LConnection);
end;
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
aNotif( 'DB_Background', 'DB Background', 'DB ListView aktarma bitti...' );
end);
end).Start;
end;
procedure TForm1.aNotif( aName, aTitle, aBody : String );
var
LNotification: System.Notification.TNotification;
begin
With System.Notification.TNotificationCenter.Create(nil) do
try
if Supported then begin
LNotification := CreateNotification;
try
LNotification.Name := aName;
LNotification.Title := aTitle;
LNotification.AlertBody := aBody;
PresentNotification(LNotification);
finally
LNotification.Free;
end;
end;
finally
Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutdown := true;
FDGUIxWaitCursor := TFDGUIxWaitCursor.Create(nil);
FDPhysSQLiteDriverLink := TFDPhysSQLiteDriverLink.Create(nil);
FDGUIxAsyncExecuteDialog := TFDGUIxAsyncExecuteDialog.Create(nil);
FDPhysSQLiteDriverLink.DriverID := 'SQLite';
FDGUIxWaitCursor.Provider := 'FMX';
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FreeAndNil(FDGUIxWaitCursor);
FreeAndNil(FDPhysSQLiteDriverLink);
FreeAndNil(FDGUIxAsyncExecuteDialog);
end;
ListView Veri doldurma esnasında TTask kullanımı - kornakamil - 14-02-2021 Üstad örnek harika kafamdaki tüm soruların cevabı örneğin içinde . Ben kodlamaya Clipper ile başlamıştım . Kod yazmaktan yüksünmem ama sanırım Visual proğramlar bizi biraz tembelliğe alıştırdı. Emeğinize sağlık. Saygılar ListView Veri doldurma esnasında TTask kullanımı - mrmarman - 14-02-2021 @Tuğrul HELVACI çok haklı olarak, çok ama çok önemli hatama dikkatimi çekti. Acele ile yazınca oluyor böyle hatalar ama bu fahiş hata sayılanlardan, yani özürü yok MemoryLeak bir projede en kaçınılması gereken hatalardan biridir. Buradaki örnekte OnCreate olayına konacak kısmı Button altına koyunca her butona basışta var olan nesneye bir yenisi eklenerek şişiyor olduğunu fark etmemişim. Ayrıca Thread içerisinde aynı connection'u kullanmışım, ona da bir ek connection create edilmesi sağlandı. Kaynak kodun üzerini çizerek yenisini yolluyorum.
Uses System.IOUtils,
System.Notification,
Data.DB,
FireDAC.Stan.Intf,
FireDAC.Comp.UI,
FireDAC.FMXUI.Wait, {FDGUIxWaitCursor.Provider := 'FMX'}
FireDAC.DApt,
FireDAC.Comp.Client,
FireDAC.Stan.Param,
FireDAC.Stan.Def,
FireDAC.Stan.Async,
FireDAC.Phys.Intf,
FireDAC.Phys.SQLiteWrapper.Stat,
FireDAC.Phys.SQLite;
Var
FDGUIxWaitCursor : TFDGUIxWaitCursor;
FDPhysSQLiteDriverLink : TFDPhysSQLiteDriverLink;
FDGUIxAsyncExecuteDialog : TFDGUIxAsyncExecuteDialog;
FDBFileName : String;
procedure TForm1.DB_Prepare( dbName: String = 'dbSqlite.db' );
Var
LConnection : TFDConnection;
LQuery : TFDQuery;
LRes : TResourceStream;
begin
{$if Defined(MSWINDOWS)}
FDBFileName := System.IOUtils.TPath.Combine( TPath.Combine(GetCurrentDir, 'DATA'), dbName);
{$elseif Defined(ANDROID)}
FDBFileName := TPath.Combine( TPath.Combine( TPath.GetDocumentsPath, 'DATA'), dbname);
{$endif}
if NOT DirectoryExists ( ExtractFilePath(FDBFileName))
then ForceDirectories( ExtractFilePath(FDBFileName) );
aNotif( 'DB_Background', 'DB Path', FDBFileName );
if NOT FileExists( FDBFileName ) then
begin
LConnection := TFDConnection.Create( nil );
LConnection.Params.Values['DriverID'] := 'SQLite';
LConnection.Params.Values['database'] := FDBFileName;
LQuery := TFDQuery.Create( nil );
try
LQuery.Connection := LConnection;
LQuery.SQL.Text := ''
+ 'CREATE TABLE ''OrnekTable'' ('
+ ' ''id'' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,'
+ ' ''Ad'' varchar(255) default NULL,'
+ ' ''DogTar'' varchar(255),'
+ ' ''Adres'' varchar(255) default NULL,'
+ ' ''Telefon'' varchar(100) default NULL )'
;
try
LQuery.ExecSQL;
except
aNotif( 'DB_Background', 'DB Cretation', 'CREATE Edilemedi...' );
Exit;
end;
LRes := TResourceStream.Create( HInstance, 'SampleData', RT_RCDATA );
try
LQuery.SQL.LoadFromStream( LRes );
LQuery.ExecSQL;
finally
FreeAndNil(LRes);
end;
LConnection.Commit;
finally
FreeAndNil(LQuery);
FreeAndNil(LConnection);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DB_Prepare();
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
TThread.CreateAnonymousThread(procedure ()
var
LQuery : TFDQuery;
LConnection : TFDConnection;
begin
LConnection := TFDConnection.Create(nil);
LQuery := TFDQuery.Create( nil );
try
LQuery.Connection := LConnection;
LConnection.Params.Values['DriverID'] := 'SQLite';
LConnection.Params.Values['database'] := FDBFileName;
LQuery.SQL.Text := 'SELECT * FROM ''OrnekTable'' ';
LQuery.Active := True;
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
aNotif( 'DB_Background', 'Rescord Count', InttoStr(LQuery.RecordCount) );
end);
while NOT LQuery.Eof do
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
ListView1.Items.Add.Text := Format( '%s : %s', [ LQuery.FieldByName('Ad').AsString, LQuery.FieldByName('DogTar').AsString ] );
end);
LQuery.Next;
end;
LQuery.Active := False;
finally
FreeAndNil(LQuery);
FreeAndNil(LConnection);
end;
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
aNotif( 'DB_Background', 'DB Background', 'DB ListView aktarma bitti...' );
end);
end).Start;
end;
procedure TForm1.aNotif( aName, aTitle, aBody : String );
var
LNotification: System.Notification.TNotification;
begin
With System.Notification.TNotificationCenter.Create(nil) do
try
if Supported then begin
LNotification := CreateNotification;
try
LNotification.Name := aName;
LNotification.Title := aTitle;
LNotification.AlertBody := aBody;
PresentNotification(LNotification);
finally
LNotification.Free;
end;
end;
finally
Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutdown := true;
FDGUIxWaitCursor := TFDGUIxWaitCursor.Create(nil);
FDPhysSQLiteDriverLink := TFDPhysSQLiteDriverLink.Create(nil);
FDGUIxAsyncExecuteDialog := TFDGUIxAsyncExecuteDialog.Create(nil);
FDPhysSQLiteDriverLink.DriverID := 'SQLite';
FDGUIxWaitCursor.Provider := 'FMX';
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FreeAndNil(FDGUIxWaitCursor);
FreeAndNil(FDPhysSQLiteDriverLink);
FreeAndNil(FDGUIxAsyncExecuteDialog);
end;
|