Listview thread yöntemini

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
hido
Üye
Mesajlar: 268
Kayıt: 29 Mar 2014 04:32

Listview thread yöntemini

Mesaj gönderen hido »

Merhaba; Databadeki veriler çok fazla olduğundan listviewe listelemek için çok bekliyorum, forumda ve nette yaptığım araştırmalarda Thread yöntemini fazlasıyla bahsedilmiş fakat Thread ile ilgili listeleme için hiç örnek bulamadım bu konuda nasıl yöntem izleyebilirim...

Kod: Tümünü seç

begin
  try
    ListView.Items.Clear;
    with PLAYLISTQuery do
    begin
      Close;
      SQL.Clear;
      SQL.Add('Select * From PLAYLIST');
      SQL.Add('Order By SIRANO ASC');
      SQL.Add('Limit 0,10000');
      Prepared := True;
      Open;
      while Not Eof do
      begin
        with ListView.Items.Add do
        begin
          Caption := IntToStr(PListView.Items.Count);
          SubItems.Add(FieldByName('sanatci').AsString);
          SubItems.Add(FieldByName('suresi').AsString);
          SubItems.Add(FieldByName('tarihi').AsString);
          Next;
        end;
      end;
    end;
  except
  end;
end;
Kullanıcı avatarı
Lost Soul
Üye
Mesajlar: 1064
Kayıt: 01 Nis 2007 02:55
Konum: mekan ANKARA toprak ELAZIĞ
İletişim:

Re: Listview thread yöntemini

Mesaj gönderen Lost Soul »

İstediğiniz şey beklerken uygulamanın kilitlenmesini engellemek ve dilediğinizde iptal etmek ise bunun için threade ihtiyacınız yok

Kod: Tümünü seç

while Not Eof do
      begin
satırından hemen sonra Application.ProcessMessages yazarak kilitlenmeyi engelleyebilir
ve
Formunuzda (TForm class da) IslemiDurdur = false bir boolean değişken oluşturup

Kod: Tümünü seç

 while (Not Eof) and (IslemiDurdur = false)  do
      begin
ile işlemin buttonclick ya da iptal edecek yerde True edilmesini kontrol edebilirsiniz.
ertank
Kıdemli Üye
Mesajlar: 1653
Kayıt: 12 Eyl 2015 12:45

Re: Listview thread yöntemini

Mesaj gönderen ertank »

Merhaba,

Uygulamanın Client/Server yapısını bilmeden yazıyorum. Yazdıklarım size uygun olmayabilir.

Farklı bir düşünce olarak Query sonucu parça parça alınabilir mi? Eğer kullandğınız Query nesnesi FetchCount, FetchAll gibi bir özellikler kullanıyorsa bunlardan faydalanabilirsiniz belki.

Örneğin Query kayıtları 1000'lik partiler halinde getirecek şekilde ayarlanıp kullanıcı sonraki 1000 kaydı görmek istediğinde Query'e bir sonraki parçayı "fetch" et denilebilir diye geçti aklımdan.
Kullanıcı avatarı
G.Arkas
Üye
Mesajlar: 829
Kayıt: 01 Eki 2007 07:16
Konum: İstanbul
İletişim:

Re: Listview thread yöntemini

Mesaj gönderen G.Arkas »

Özel bir thread bulmanız zor. Ancak basit bir TThread nesnesi oluşturup içine kodlarınızı ekleyebilirsiniz. Hızlıca yazıyorum hata olabilir, iyice kontrol edin.

Kod: Tümünü seç

type
  TListeleme = class(TThread)
  private
    { Private declarations }
    //Dışarıdan alınacak parametreler buraya
  procedure listeCek;
  public
    constructor Create(CreateSuspended: boolean);
  protected
    procedure Execute; override;
    
    constructor TListeleme.Create(CreateSuspended: boolean);
begin
  inherited Create(CreateSuspended);
   //Dışarıdan alınacak parametreler burada doldurulur.
end;

procedure TListeleme.ListeCek;
begin
  try
    ListView.Items.Clear;
    with PLAYLISTQuery do
    begin
      Close;
      SQL.Clear;
      SQL.Add('Select * From PLAYLIST');
      SQL.Add('Order By SIRANO ASC');
      SQL.Add('Limit 0,10000');
      Prepared := True;
      Open;
      while Not Eof do
      begin
        with ListView.Items.Add do
        begin
          Caption := IntToStr(PListView.Items.Count);
          SubItems.Add(FieldByName('sanatci').AsString);
          SubItems.Add(FieldByName('suresi').AsString);
          SubItems.Add(FieldByName('tarihi').AsString);
          Next;
        end;
      end;
    end;
  except
  end;
end;
procedure TListeleme.Execute;
begin
  ListeCek;
end;

  end;
çağırmak için

Kod: Tümünü seç

TListeleme.Create(False);
Resim
Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 216
Kayıt: 09 Tem 2003 10:04

Re: Listview thread yöntemini

Mesaj gönderen Opt2000 »

Merhaba,

Sizin sorununuz çok fazla verinin ListView'de listelenmesi. Application.ProcessMessages ve Thread kullanmak sorununuzu çözmez. İşin doğrusu daha da kötü hale getirir. Çünkü bu iki yapı da işlem uzun sürerken formun kilitlenmemesini sağlar (Application.ProcessMessages kötü bir yöntem, G.Arkas'ın verdiği Thread örneği de yanlış, çünkü senkronizasyon yapmıyor. VCL bileşenleri thread-safe değildir). Bu da programın listelemek dışındaki işlemler için da vakit harcaması demek. Yapabileceğiniz iki değişiklik var:

1. BeginUpdate/EndUpdate kullanmak
Şu an kullandığınız yapıda, listview'e her yeni Item eklediğinizde ListView kendini güncellemeye çalışıyor. Bu yüzden de işlem çok yavaş oluyor. Oysa kodu şu şekilde yazacak olursanız işlem çok hızlanacaktır:

Kod: Tümünü seç

begin
  try
    with PLAYLISTQuery do
    begin
      Close;
      SQL.Clear;
      SQL.Add('Select * From PLAYLIST');
      SQL.Add('Order By SIRANO ASC');
      SQL.Add('Limit 0,10000');
      Prepared := True;
      Open;
      
      ListView.Items.BeginUpdate;
      try
        ListView.Items.Clear;
        while Not Eof do
        begin
          with ListView.Items.Add do
          begin
            Caption := IntToStr(PListView.Items.Count);
            SubItems.Add(FieldByName('sanatci').AsString);
            SubItems.Add(FieldByName('suresi').AsString);
            SubItems.Add(FieldByName('tarihi').AsString);
            Next;
          end;
        end;
      finally
        ListView.Items.EndUpdate;
      end;
    end;
  except
  end;
end;
2. Eğer bu yeterli gelmezse ListView'i virtual data ile kullanabilirsiniz. Bunun için OwnerData özelliğini kullanmanız gerekiyor. Anlatması uzun, ama Delphi'nin dokümanlarından okuyabilirsiniz.

Bu iki madde dışında bir iki tavsiyem olacak:
1. with x do yapısını kullanmayın. Kod yazarken pratik gibi görünse de hem okumayı, hem de debug işlemini çok zorlaştırıyor. Ve hatta kimi zamanlarda farkında olmadan hata yapmanıza da sebep olabiliyor.

2. Hiding Exception vs Handling Exceptions konusunu araştırın. Bütün kodu try/except bloğuna almışsınız. Bir hata olduğu zaman bunu kullanıcı bilmeyecek. Kod hata düzeltmeye de çalışmıyor. Sonuçta hatayı saklamış oluyorsunuz. Ayrıca Java, C# gibi dillerde try/catch bloklarının kodun çalışma hızına bir maliyeti yoktur (hata oluşana kadar), ama Delphi, C++ gibi dillerde try/catch/except bloğu kodu inanılmaz derecede yavaşlatır. Bu durum dillerin yapısından kaynaklanıyor. Eğer hatayı yönetmeyecekseniz try/except bloğu kullanmayın. Bırakın program hata versin. Eğer kullanıcıya detay vermek istemiyorsanız Application.OnException eventini kullanın. Burada hem hatayı üreten nesneyi, hem de hata nesnesini alırsınız. Eğer isterseniz log tutarsınız, isterseniz kullanıcıya düzgün bir mesaj verirsiniz.

İyi çalışmalar
Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 216
Kayıt: 09 Tem 2003 10:04

Re: Listview thread yöntemini

Mesaj gönderen Opt2000 »

Bu arada eğer Thread'lerle ilgili detaylı ve Türkçe doküman isterseniz Tuğrul Helvacı'nın sitesinde çok güzel konu anlatımları bulabilirsiniz.

http://www.tugrulhelvaci.com/

Sitede Thread dışında da çok güzel konu anlatımları var. İşin güzel tarafı konu anlatımları ucuz çeviriler değil. Tuğrul Bey yazdıklarını bilerek yazmış. Bu yüzden de özel bir tebriği hakediyor bence :)
Kullanıcı avatarı
kimimben
Üye
Mesajlar: 129
Kayıt: 28 Oca 2016 04:41
Konum: İstanbul

Re: Listview thread yöntemini

Mesaj gönderen kimimben »

Opt2000 yazdı: Bu iki madde dışında bir iki tavsiyem olacak:
1. with x do yapısını kullanmayın. Kod yazarken pratik gibi görünse de hem okumayı, hem de debug işlemini çok zorlaştırıyor. Ve hatta kimi zamanlarda farkında olmadan hata yapmanıza da sebep olabiliyor.
İyi çalışmalar
Bu doğru.
Aynı kodu with x ve with x yapısını kullanmadan iki method yazın.
Daha sonra Project -> QA Metrics... menüsünden kod metric aracını çalıştırın.
Resim
Yazılan methodları incelediğinizde with x ile yazılan kodun complexity değeri daha büyük olacaktır.
Buda kodun daha karmaşık ve anlaşılamaz olduğunun göstergesidir.
Kullanıcı avatarı
fesiharslan
Üye
Mesajlar: 591
Kayıt: 20 Eki 2006 11:37
Konum: Erzurum
İletişim:

Re: Listview thread yöntemini

Mesaj gönderen fesiharslan »

Merhaba;
Hangi method (Button1Click mi? FormCreate mi?) daha karmaşık veya kompleks görünüyor?

Resim
Kullanıcı avatarı
hido
Üye
Mesajlar: 268
Kayıt: 29 Mar 2014 04:32

Re: Listview thread yöntemini

Mesaj gönderen hido »

Emeği gecen herkese teşekkür ederim; Konuda geçen tüm yöntemleri test ettim aşşağı yukarı hepsi verileri aynı zamanda listeliyor.

FDQuery1 özelliklerinde de "FetchCount, FetchAll" özelliği yok! aklıma gelen bir yöntem ise ilk yüz kaydı listelemek kullanıcı lisviewi aşşağıya doğru kaydırdıkca parça, parça "100" gibi litsviewe eklenecek, kafada kurdum fakat bunu kodlamaya dönkemedim,
ertank
Kıdemli Üye
Mesajlar: 1653
Kayıt: 12 Eyl 2015 12:45

Re: Listview thread yöntemini

Mesaj gönderen ertank »

Kullandığın Query nesnesini bilmiyordum. Yazdığına göre FireDAC kullanıyorsun. FireDAC bahsettiğimiz özelliği destekler.

FetchOptions içinde RowSetSize değerini kaç satır almak istiyorsan o kadar yap. Örneğin 200 satır için oraya 200 değerini yaz.
Kullanıcı avatarı
kimimben
Üye
Mesajlar: 129
Kayıt: 28 Oca 2016 04:41
Konum: İstanbul

Re: Listview thread yöntemini

Mesaj gönderen kimimben »

fesiharslan yazdı:Merhaba;
Hangi method (Button1Click mi? FormCreate mi?) daha karmaşık veya kompleks görünüyor?

Resim
Merhaba
kimimben yazdı:Aynı kodu with x ve with x yapısını kullanmadan iki method yazın.
Cümlesi ve biraz da eklediğim ekran görüntüsü yanıltmış olabilir.

Button1Click methodunun Cyclomatic Complexity (CC) değerinin,FormCreate methoduna göre büyük olması normal.
Çünkü Cyclomatic Complexity (CC) metriği,if,for,while case komutlarında ki branch/dal,blok sayısına göre ölçülüyor.

Button1Click ve FormCreate methodlarını CC'ye göre değerlendirmek ne kadar doğru olabilir.
Button1Click methodu içersinde en az bir for ve if komutu bulunuyorken,FormCreate methodu içersinde if,for ,while,case gibi komutlardan herhangi biri bulunmuyor.Haliyle FormCreate methodunun CC'değerinin daha düşük olması normal.

@hidonun yazdığı kodu with x ve with x'siz olarak iki ayrı method içersinde test ettiğimde;
with kullanmadan.

Kod: Tümünü seç

procedure TForm2.Button1Click(Sender: TObject);
var
  item: TListItem;
begin
  try
    PLAYLISTQuery.Close;
    PLAYLISTQuery.SQL.Clear;
    PLAYLISTQuery.SQL.Add('Select * From PLAYLIST');
    PLAYLISTQuery.SQL.Add('Order By SIRANO ASC');
    PLAYLISTQuery.SQL.Add('Limit 0,10000');
    PLAYLISTQuery.Prepared := True;
    PLAYLISTQuery.Open;
    ListView.Items.BeginUpdate;
    try
      ListView.Items.Clear;
      while Not PLAYLISTQuery.Eof do
      begin
        item := ListView.Items.Add;
        item.Caption := IntToStr(ListView.Items.Count);
        item.SubItems.Add(PLAYLISTQuery.FieldByName('sanatci').AsString);
        item.SubItems.Add(PLAYLISTQuery.FieldByName('suresi').AsString);
        item.SubItems.Add(PLAYLISTQuery.FieldByName('tarihi').AsString);
        Next;
      end;
    finally
      ListView.Items.EndUpdate;
    end;
  except
  end;
end;
with kullanarak

Kod: Tümünü seç

procedure TForm2.FormCreate(Sender: TObject);
begin
  try
    with PLAYLISTQuery do
    begin
      Close;
      SQL.Clear;
      SQL.Add('Select * From PLAYLIST');
      SQL.Add('Order By SIRANO ASC');
      SQL.Add('Limit 0,10000');
      Prepared := True;
      Open;
      ListView.Items.BeginUpdate;
      try
        ListView.Items.Clear;
        while Not PLAYLISTQuery.Eof do
        begin
          with ListView.Items.Add do
          begin
            Caption := IntToStr(ListView.Items.Count);
            SubItems.Add(FieldByName('sanatci').AsString);
            SubItems.Add(FieldByName('suresi').AsString);
            SubItems.Add(FieldByName('tarihi').AsString);
            Next;
          end;
        end;
      finally
        ListView.Items.EndUpdate;
      end;
    end;
  except
  end;
end;
Ölçüm sonuçları
Resim

Evet embarcadero yetkililerinin acilen,with metriği konusunda çalışmaya başlamaları veya CC metriği içersine with komutunuda dahil etmeleri gerektiğini anlıyoruz.
Kullanıcı avatarı
kimimben
Üye
Mesajlar: 129
Kayıt: 28 Oca 2016 04:41
Konum: İstanbul

Re: Listview thread yöntemini

Mesaj gönderen kimimben »

Opt2000 yazdı:Ayrıca Java, C# gibi dillerde try/catch bloklarının kodun çalışma hızına bir maliyeti yoktur (hata oluşana kadar), ama Delphi, C++ gibi dillerde try/catch/except bloğu kodu inanılmaz derecede yavaşlatır. Bu durum dillerin yapısından kaynaklanıyor.
Merhaba
İkisi arasında ki farkı merak ettim araştırıyorum. :roll:
anonymousdelphicoder
Üye
Mesajlar: 152
Kayıt: 16 May 2014 11:23

Re: Listview thread yöntemini

Mesaj gönderen anonymousdelphicoder »

@kimimben +1
Cevapla