Döngü yerine Thread.

FireMonkey ve Mobil uygulama (iOS, Android, Windows Phone) ile ilgili sorularınızı bu foruma sorabilirsiniz.
Kullanıcı avatarı
RADCoder
Üye
Mesajlar: 129
Kayıt: 21 Ara 2013 04:03

Döngü yerine Thread.

Mesaj gönderen RADCoder »

Merhabalar,
Bu konuyu açarken çok düşündüm, ama bilmek istediyimden dolayı konuyu açmak zorunda kaldım..
Bu forumda Thread-larla ilgili bir çok konu buldum ama hepsinde farklı konulara sabitlenmiş gördüm..

Belkide sorum hatalı yada yalnış ola bilir ama hiç kullanmadığım ve anlamak istediyim içindir.
Muharrem abi belkide bu konu için bana kızacaktır. Ancak niyetim hazır kod almak yada burdan aldığım kodlarla kopyala yapıştır yapmak deyil, kaynak bulamama sıkıntısıdır.

Sorum: Her hangi bir listeleme ve ya döngü işleminde kullandığımız "for" yada başka döngüleri kullanarak, toplu bilgi alma işlemini Threadla yapa bilirmiyiz.
Yapıla biliyorsa nerden başlamam gerek hangi kaynağı yada hangi bilgiyi araştırmalıyım?

Örnek:

Kod: Tümünü seç

var
  i: Integer;
begin
    for i := 0 to 100 do
    begin
ListBox1.Items.Add(InttoStr(i));
    end;
Yukarda yazdığım kodu Thread olarak nasıl kullanmam gerek
yada for olarak değilde Threadla döngü kurmak mümkünmüdür?

Teşekkürler..
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü yerine Thread.

Mesaj gönderen mrmarman »

Merhaba.

- Thread konusu @thelvaci (Tuğrul HELVACI)'nın özel ilgi alanına giriyor. Kendisi bu başlığı görürse fikrini paylaşacaktır.

- Fikrimi paylaşmadan önce ne hakkında konuştuğumuzu temellendirmek için terminolojik olarak paydaları eşitleyelim.

(1) Ana projemiz tek kulvarlı bir yüzme havuzudur.
(2) Thread kurduğumuz zaman bu yüzme havuzuna ek olarak ikinci, üçüçüncü ... (n)nci, yani kurduğunuz thread sayısı kadar ek kulvar oluşturmuş oluyoruz.

(3) Şimdi bu kulvarlar arasında ilişki yoksa asenkron davranış diyoruz. Yani kulvarlardan birisi yürürken diğerinin ne kadar ileride veya geride kalacağının önemi yoktur demek.
(4) Eğer bir kulvardaki ilerleme, diğer kulvarda gerçekleşen bir işe/ilerlemeye göre farklı davranması gerekiyorsa buna da senkronize davranmak diyoruz.

Buraya kadar tamam sanırım. İşte thread kurarken döngü dediniz ya... Bu senkron olma durumu için önemli bir karar vermek gerekiyor. Eğer döngünün sonucu (1) nolu thread olan ana proje katmanında önemsiz ise asenkron ilişki söz konusudur.

Bu mihmalde sorunuzu "Bu döngüler ne amaç ile kullanılacak?" şeklinde güncelleyin ona göre cevabı genişletelim.
Resim
Resim ....Resim
Kullanıcı avatarı
RADCoder
Üye
Mesajlar: 129
Kayıt: 21 Ara 2013 04:03

Re: Döngü yerine Thread.

Mesaj gönderen RADCoder »

Merhabalar, Güzel cevabınız için size mennetdarım Allah sizden razı olsun Muharrem abi..

Aslında konuşmam gerekirse uzun uzadı olur bence..
Fikrimce Javada yapalın işlemler çok daha hızlı.
Aynı işlemi Delphi-de yaptığımda çok gecikmelere rastladım.
Java programcısının verdiği öneride aynı oldu "Thread"..

Tam olarak aynı işlemi yapıyoruz..
Mesela, Diyelim JSON olarak bir parseleme yapıyorum. Aldığım veri yığınını yada sonucu listeliyorum.
Tabi bu işlemin arasında resimde çekiyorum.
Şimdi bunları Bir ListView üzerinde for döngüsü kullanarak listelemeye kalktığımda parseleme, ardından resim çekme (Her İD ve s. göre) işemi uzuyur, üstüne üstlük
Tabconrol içindeki İtemlerde kaydırma işlemi varsa haraketler donarak yada kesik kesin haraket etdiyor..
Şu an için Parse işleminde bana dönen bilgi sayısı çok ufak, ama ilerde sayı çoğaldıkca uzama süreside çoğalacağı kesindir..

Bu bilgileri Trhead içinde nasıl almalıyım yada nerden yola çıkmalıyım?

Cevabınız için tekrar teşekkür ederim..
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü yerine Thread.

Mesaj gönderen mrmarman »

Bir linkten çekilen çok sayıda bağımsız veri bloğu söz konusu ise, thread biçilmiş kaftan. Ancak çekilen verinin parse işleminden sonra doğru yere konumlandırılması / yönlendirilmesi gerekecektir.

Örneğin bir listbox'da 100 adet filmi listelediniz. İkinci turda bu her bir filmin önce içerik kısmını, ardından da resim linklerini indirmeye çalışırsanız 100 adet filmin tamamlanması görsel olarak zaman alacaktır.

Senaryo:

(1) (1)'den başlayıp (100)'e kadar filmlerin adım adım ListView'e eklendiğini ele alalım. (1) nolu film eklendi.
(2) Bunun URL'sinden önce (1) nolu filmin bilgilerini download etmek üzere bir thread açılacaktır.
(3) Aynı paralelde bir thread de bilinen Resim URL'sinden Resminin download edilmesi üzerine bir thread açılacaktır.

(*) Bu arada (1) nolu filmin bilgi alma işi bitmiştir (2) nolu filme ulaşmıştır. Bu durumda ne yapılacağına karar vereceksiniz.

(a) Bu iki thread bitip sonra mı (2) nolu film için baştan mı başlayacaksınız.

(b) Yolunuza devam edip (1) Proje Katmanı (2) 1.filmin bilgileri, (3) 1.filmin resmi, (4) 2.filmin bilgileri, (5) 2.filmin resmi ..... gidecek bu arada biten threadler free olacağından aynı anda en fazla -internet hızınıza göre örnek olarak atıyorum- (4) thread aktif kalacaktır.

Bu threadlerin işi ne zaman bitecek, bitince ne yapacaksınız ?

- İlgili ListView'in ilgili kayda ilişkin satırına geri dönüp bu edinilen alt bilgileri oraya yazacaksınız
- İnridilen resmi de İlgili ListView'in ilgili kayda ilişkin ilgili resim alanına koyacaksınız ki bu da gerekli.

Geriye her thread sonunda hangi ListView Item Index'ine başvurulacağını bir listede tutmanız ve bu listeyi de ayrı bir fonksiyon ile tüketmeniz gerekecektir.

Gözünüzü korkutmasın anlatması uzun ama uygulaması basit bir işlemdir. Tecrübe kazanana kadar kağıt üzerinde planlayıp öyle işleme başlamanızı öneririm. :idea:
Resim
Resim ....Resim
Kullanıcı avatarı
RADCoder
Üye
Mesajlar: 129
Kayıt: 21 Ara 2013 04:03

Re: Döngü yerine Thread.

Mesaj gönderen RADCoder »

Muharrem abi, öncelikle konuya tam girmeden evel bir hususu beyan etmiş olayım.
İlk yazımdada belirtdiğim gibi Thread hakkında bilgim olmadığı için konuyu açtım.
Yani nasıl kullanılır örneği nedir bilimiyorum..
Sizin deyiminiz üzere sölersem Havuzda yüzen yüzücülerin şeridini nasıl inşa edeceğimi bilmiyorum..

Diğer taraftan bilgi alma ve listeleme sizinde dedğiniz gibi yavaş ve zaman alıcı..

Ama kafama takılan kısım resim almadanda bilgi aldığımda bilgiler internet hızana görede bekletiyor..
Sizce bu normalmidir?

Şimdi İlk önce kodları izah etmekle yola çıkmak istiyorum.
Şöyle bir kod yazdım, bu kodla kategorileriin islimlerini listeleyip ve içinde kaç bilgi olduğunu kullanıcıya gösteriyorum.

Kod: Tümünü seç


.....
uses XSuperObject, XSuperJSON;
.....

//// Kateqoriyi listeliyorum /////
procedure TF_menu.kategori_load;
var
   LBItem : TListBoxItem;
   X : ISuperObject;
   J: Integer;
begin
   ListBox1.Items.Clear;

   X := TSuperObject.Create(call('http://benimsitem....com/?~/az/api/kateqori/'));

   with X.A['tipler'] do

for J := 0 to Length -1 do
begin Obj := O[J]; begin
   LBItem:=TListBoxItem.Create(ListBox1);
   LBItem.Text:=Obj.S['name']+'  ('+Obj.I['count'].ToString+')';
   LBItem.Height:=48;
   LBItem.ItemData.Accessory:=TListBoxItemData.TAccessory(1);
   ListBox1.AddObject(LBItem);
end;

end;
end;
ListBoxta listeledikden sonra ListBoxİtem olayına ise şu kodları yazıp her itemindex-de bulanan ilan sayısı kadar ListView-e listeliyorum.
Burada Bilgiler ve Resimler LItem-lere ekleniyor..

Kod: Tümünü seç

procedure TF_Splash.ListBox1ItemClick(const Sender: TCustomListBox;
  const Item: TListBoxItem);
var
   X,  KX, KObj: ISuperObject;
  J: Integer;
  LItem: TListViewItem;
  MS : TMemoryStream;
  GIf: TBitmap;
begin
  ListView1.Items.Clear;


  X := TSuperObject.Create(call('http://site.com/?~/az/api/kategoriler/'));
  KX := TSuperObject.Create(call('http://site.com/?~/az/api/cat/'+X.A['tipler'].O[ListBox1.ItemIndex].I['id'].ToString+'/0/5'));

  if (KX.I['count_all'].ToString > IntToStr(0)) then
begin

  with KX.A['elanlar'] do

  for J := 0 to Length -1 do
begin
  KObj := O[J];

begin
  LItem := ListView1.Items.Add;
  LItem.Height:=100;
  LItem.Data[TMultiDetailAppearanceNames.Detail1] := Format(KObj.S['qiymet']+' AZN',  [Litem.Index]);
  LItem.Data[TMultiDetailAppearanceNames.Detail2] := Format('Oda Sayı: '+KObj.S['otaq']+' oda'+#13#10+'Erazi: '+KObj.S['sahe']+' kv/m',  [Litem.Index]);
  LItem.Data[TMultiDetailAppearanceNames.Detail3] := Format('Bölge: '+ KObj.S['ssheher']+' '+KObj.S['rrayon']+#13#10+#13#10+DateToStr(Date),[Litem.Index]);
  LItem.Data[TMultiDetailAppearanceNames.Detail4] := Format(KObj.S['id'],[Litem.Index]);

  MS := TMemoryStream.Create;
  GIf := TBitmap.Create;
  try
  IdHTTP1.Get('http://site...com/upload/site/'+'/'+KObj.S['id']+'/'+IntToStr(1)+'_small.jpg',MS);
  Ms.Seek(0,soFromBeginning);
  Gif.LoadFromStream(MS);
  Image9.Bitmap.Assign(GIF);
  finally
  FreeAndNil(GIF);
  FreeAndNil(MS);
  end;
  LItem.Bitmap:=Image9.Bitmap;
end;
end;

end;
TabItemSonuclar.ExecuteAction(ChangeTabActionSonuclar);
end;
İlk önce yazdığım kodlar hakkında fikrinizi almak isterim yalnışlarımı ortadan kaldırmak maksatlı.
İkinci olarak Thread için küçük bir örnek linki bile olursa kafi..
Devamında inşallah toplu düzenlemeler yapmaya çalışıp takılmış olduğum yerlerden sorarım izninizle..

Tekrar teşekkür ederim.. Allah razı olsun..
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü yerine Thread.

Mesaj gönderen mrmarman »

- Buradan kodları gözle okuyarak yorumlamaya çalışıcam.

(1) Birinci Faz olarak ListBox1'e bir liste oluşturdun. Buraya kadar tamam.
(2) İkinci faz olarak ise bu ListBox1'in herhangi bir itemine tıkladığında, ListView1'deki tüm itemleri temizleyip işleme başlamışsın. Bu da demek oluyor ki, ListView1 nesnen, ListBox1'in detay ekranıdır... (Mesajında da bu şekilde demişsin zaten"her itemindex-de bulanan ilan sayısı kadar ListView-e listeliyorum.")
- SENARYO -
(3) Bu aşamada bir ListBox1'in bir item'ine tıkladığında o Iteme ait (10) tane ilan olduğuna ilişkin bilgiye sahibiz diyelim. yani KX.A['elanlar'].Length değeri (10) yani döngü indexi (J) değişkeninin içeriği [0]..[9] arasında olacak.
(4) Senin Thread kurgun bu aşamada gerçekleşecek. Her (J) değeri için bir thread açman gerekecek.
(5) Açtığın her thread için bir ListView Item'ini rezerve edeceksin. Çünkü thread sonunda veriler bu rezerve ettiğin yere aktarılacaktır. Bunun için thread içerisinde, bu thread ile elde edilecek verinin hangi ListView Itemine ait olduğunu biliniyor olması gerekir. Bu da şu demektir, ListView'e item ekledikten sonra o iteme unique bir değer vereceksin.
(6) Daha sonra thread kendiliğinden sona erdiğinde ListView1'in mevcut Item'lerini 0'dan başlayıp Item sayısı kadar bir döngü kurarak bu unique değeri bulduğu anda, threadin ilgilendiği asıl Item'in bu olduğu sonucuna varmasını bekleyeceksin. Böylece rezerve ettiğin iteme thread tarafından elde edilen detayların girilmesini sağlayacaksın.

(*) Sana ve bu başlığı okuyacak herkes için konuyu anlayabilmeniz için hatta senin listbox mantığını da içine alan basit bir örnek hazırladım. :idea:

Bu örneği alıp inceleyin, çok basit bir işlemdir. Bundan sonra bu başlığı okuyanlar için söylüyorum tadından yenmez derler ya, sonradan otomatik vitesli araba alanların (ben dahil) daha önce neden bugüne kadar manuel vites araba kullandım diyenler gibi, threadsiz bir hayat var mıymış diyeceğine eminim diyebilirim :bravo:

- Aşağıda verdiğim kod metodik olarak xKanal ismindeki tek bir global değişken için üç defa create işlemi aslından doğru değildir. Size çalışma mantığını anlatabilmek için bir metaya ihtiyacım vardı ondan verdim.

- Bu şekilde de çalışmasına çalışıyor ama olması gereken hali aslında xKanal global değişkenini silip şu verdiğim şekilde yapabilirsiniz. Bu forumda sıkça yaşadığım, konunun esasından uzaklaşan eleştiri mesajları ihtimaline karşı bu açıklamayı da peşinen eklemek zorunda hissettim. :alsana:

Kod: Tümünü seç

    With TBirDonguKanali.Create(False) do
    begin
      OnTerminate := KanalBitti;
      ListBox1.Items.Add( IntToStr( ThreadID ) ); // Eklen Thread'in kendi Unique ID'si
      ListBox2.Items.Add( '0' ); // Bekleme Süresi (thread içinden güncellenecek)
    end;

Resim

Kod: Tümünü seç

Uses DateUtils;

type
  TBirDonguKanali = class(TThread)
  protected
    procedure Execute; override;
  end;

Var
  xKanal  : TBirDonguKanali;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  if ListBox1.Items.Count < 3 then
  begin // 3 Kanal ile sınırlandırdık...
    xKanal             := TBirDonguKanali.Create(False);
    xKanal.OnTerminate := KanalBitti;

    ListBox1.Items.Add( IntToStr( xKanal.ThreadID ) ); // Eklen Thread'in kendi Unique ID'si
    ListBox2.Items.Add( '0' ); // Bekleme Süresi (thread içinden güncellenecek)

    ProgressBar1.Max := 10;
    ProgressBar2.Max := 10;
    ProgressBar3.Max := 10;

    case ListBox1.Items.Count of
    1: ProgressBar1.Position := 0;
    2: ProgressBar2.Position := 0;
    3: ProgressBar3.Position := 0;
    end;
  end;
end;

procedure TForm1.KanalBitti( Sender:TObject );
begin
  // Her açılan thread bittiğinde buraya da Form içinden ulaşır..
  // Dilersen burayı da kullanabilirsin.
  ShowMessage( IntToStr( TThread(Sender).ThreadID ) + ' ID''li Thread Bitti...' );
end;

{ TBirDonguKanali }

procedure TBirDonguKanali.Execute;
Var
  iSayac  : Integer;
  Zaman   : TDateTime;
  Bekleme : Integer;
  ThreadID,
  idx : Integer;
begin
  Randomize;
  Bekleme  := Random( 5 )+1; // 1 ile 5 arasında bir rakam alacak...
  ThreadID := TThread(Self).ThreadID; // Kendi Thread'imizin ID'sini böyle alıyoruz.
  idx      := Form1.ListBox1.Items.IndexOf( IntToStr( ThreadID ) ); // Hangi ITEM'e aitiz ?

  // Burada Thread içinde Form üzerindeki bir ListBox'un ilgili Itemini güncelledik.
  Form1.ListBox2.Items[idx] := IntToStr(Bekleme) + ' Saniye';

  Zaman    := Now();
  Zaman    := incSecond( Zaman, Bekleme );
  iSayac   := 0;
  while iSayac <= 10 do
  begin
    while Zaman > Now() do
    begin
      Application.ProcessMessages;
    end;
    case idx of
    0: Form1.ProgressBar1.Position := iSayac;
    1: Form1.ProgressBar2.Position := iSayac;
    2: Form1.ProgressBar3.Position := iSayac;
    end;
    Zaman := incSecond( Zaman, Bekleme );
    Inc(iSayac);
  end;
  // İlgili Item'in nihai değerini de güncelledik...
  Form1.ListBox2.Items[idx] := 'Bitti';
  // Burada sona erdi...
  inherited;
end;
Dosya ekleri
ThreadOrnegi.rar
Basit bir Thread Örneği
(204.33 KiB) 247 kere indirildi
Resim
Resim ....Resim
Kullanıcı avatarı
RADCoder
Üye
Mesajlar: 129
Kayıt: 21 Ara 2013 04:03

Re: Döngü yerine Thread.

Mesaj gönderen RADCoder »

Cevabınız için teşekkür ederim.
Sölediklerinizi ve örneği hemen incelemeye başlıyorum Muharrem abi.
Kendi Threadımı yazdıktan sonra sorunlarımı bildiririm izninizle..
Tekrar tekrar teşekkür ederim.
Kullanıcı avatarı
RADCoder
Üye
Mesajlar: 129
Kayıt: 21 Ara 2013 04:03

Re: Döngü yerine Thread.

Mesaj gönderen RADCoder »

Tekrar Merhabalar.
Muharrem abim Verdiyiniz örneği inceledim, Thread nasıl oluşturulr ve nasıl işlem gördüğünü azda olsa anlamaya çalıştım.
Tam olarak doğru anladım, diyemediyim kısımlar şunlardır.

Acaba:

Kod: Tümünü seç

Var
  iSayac  : Integer;
  Zaman   : TDateTime;
  Bekleme : Integer;
Bir TTimer görevinimi yapıyor?

Sonra:

Kod: Tümünü seç

if ListBox1.Items.Count < 3 then
  begin // 3 Kanal ile sınırlandırdık...
Şurada Buttona her tıklama yaptığımda 3 kanal sınırlamsıyla yeni bir kanal oluşturuyor.
Peki Diyelim Elimizde 10 diye bir değer var ve o değer kadar kanal oluşturmasını istersek, ve bir tıklamada 10 kanal oluşturmak için ne yapmalıyız?

Şurada:

Kod: Tümünü seç

procedure TBirDonguKanali.Execute;
Burada evvela execute nerde yada nasıl tetiklendiyini anlamak isterdim?

Prosedürün İçinde yazdığımız hertürlü kodu çalıştırırmı, yoksa kanal oluşturulurken ona uyumlumu olmak zorundamıdır?
Yani Thread içinde kanal oluştururken kanalın doğru çalışmasında bir etkisi varmıdır.

Kodla soracak olursam:

Kod: Tümünü seç

procedure TBirDonguKanali.Execute;
var
i:integer;
begin

for i := 0 to 100 do // Böyle bir kod çalışırmı?

 ......

end;
İnşallah sorularımla sizi bunaltmadım..
Herşeyin için Çok teşekkür ederim..
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü yerine Thread.

Mesaj gönderen mrmarman »

Sorularını numaralandıralım.

(1) Bir TTimer görevi kesinlikle yok... Bunun altını çizeyim. Thread örneğini verirken bir dosyanın indirilmesini simüle edecek, farklı aralıklara sahip progressbar örneği ile ifade edebileceğimi düşünmüştüm. Demek ki yanılmışım.

- Her threade yüklediğin görevin farklı sürelerde sona erebileceğini anlatmaya çalıştım. Ard arda üç tane zaman akışından sırayla (3), (1), (2) şeklinde karışık sırada bitse dahi ListBox içerisinde ilgili iteme konumlandığını örneklemek istedim. Senin de ulaşmaya çalışacağın hedef budur çünkü.

- Yani : 10 tane download başladı, (8)nci sıradaki önce bitti, sonra (3)ncü sıradaki bitti, sonra (1), (9), (5), (7) vs.vs. dağınık sırayla bitecekler bunu nasıl handle edeceğini örneklemek istemiştim.

(2) Bir tıklamada istersen 100 kanal oluştur, ancak gözetmen gereken bir şey daha var, bu kanallar dosya indirmek için çalışacak ise yeterli bant genişliğin var mı ? Hesap yapacak ise yeterli işlemci gücün var mı ? Bunun için belli bir sınırlama getirmen lazım. Sistemin akıllı olmalı. Kontrolsüz güç, güç değildir diye bir reklam sloganı vardı, gerçekten doğru bir slogan ve burada aynen geçerli.

(3) EXECUTE tetiklendiği yer bizatihi CREATE ettiğin yer ve andadır.. Kısa, yok denecek kadar kısa bir bekleme algı / kurgu süresi geçer hemen EXECUTE eventi çalışır.

(4) Thread içerisinde her türlü procedure çalıştırabilirsin. Uyum konusunda değil de anlamsız ilişkiler içinde olmaman lazım. Mesela daha download bitmeden ana thread yani projen, download bitmiş gibi dosyaya erişmeye çalışmamalı. Bilmem anlatabildim mi ? Üç, dört hatta beş boyutlu düşünmen lazım. Paralel evrenler var diye düşün.

(SONUÇ)
- THREAD'i bir Procedure veya Function gibi düşün. Tek farkı Procedure veya Function sonuçlanana kadar alt satırdaki kod çalışmaz. Thread Create ettiğinde ise direkt alt satıra geçer. Başka bir proje gibi paralel olarak yeni bir boyut açılarak orada çalışırken asıl proje de akışına hiç aralık vermeden (yani işlemin bitmesini beklemeden) yoluna devam eder.
Resim
Resim ....Resim
nguzeller
Üye
Mesajlar: 109
Kayıt: 19 Oca 2004 03:29

Re: Döngü yerine Thread.

Mesaj gönderen nguzeller »

güzel faydalı bir yazı olmuş, pc ortamında çok lazım olmuyordu ama artık mobil ile birlikte hız daha önemli hale geldi
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü yerine Thread.

Mesaj gönderen mrmarman »

- Emin olun PC ortamında da artık kullanırsınız. Çünkü artık WEB ile interaktif uygulama ihtiyaçları git gide yaygınlaşıyor.
- Basitçe, kendi projenizde donma oluşmaksızın paralel yoğun işlem yapma imkanı sunuyor. Kendi kendini update eden fonksiyonlardan tutun, ağ erişim kontrolü, ağ altında dosya transferleri, iç içe döngü yoğun hesaplamalara kadar her yerde kullanırsınız.
nguzeller yazdı:güzel faydalı bir yazı olmuş, pc ortamında çok lazım olmuyordu ama artık mobil ile birlikte hız daha önemli hale geldi
Resim
Resim ....Resim
Kullanıcı avatarı
RADCoder
Üye
Mesajlar: 129
Kayıt: 21 Ara 2013 04:03

Re: Döngü yerine Thread.

Mesaj gönderen RADCoder »

Merhabalar.

Verdiyiniz bilgiler dahil en seon cevabanız ve her ne kadar ingilizcem olmasada forumlarda kodları okumaya çalışarak Azerbaycan saati ile 08:33-e kada dayana bildim, Onda sornrası gün ışığı ve Uyku baskını yedim.. :D

Hala mantığını tam olarak anlayamadığım bir şeyin içinde kıvranıp durmaktayım.
Sabaha kadar yaptığım denemelerde her iki satırdan bir mantıksal teori kuramadığım yada kodu nerde nasıl çalıştırılacağına karar veremediyim yerler çok oldu.
Döngü içine kanal nasıl sokulur, for içinde olan J değişkeni kadar kanalın nasıl oluşturulması gerek, ThreadİD-si hafızada tururak ListView üyesine nasıl ait edilmelidir gibi binlerce soru yığını birikti kafamda..
Her döngü sırasıyla değilde sabit bir değer kadar ThreadİD si nasıl oluşturulmalı gibi çok zorluklar çıkardım kendime.
Bence bunu anlamak için Thread hakında çok fazla şey bilmek ve onu çok çok iyi anlamak gerekir..

Ortaya çıkardığım Thread işleminde (Buna Thread diyemiyorum çünki sıradan procedure gibi işliyor) normalda benim Thread olmadan işleyişimden bir farkını göremedim.
Yazdığım kodlar :

Kod: Tümünü seç


unit Unit2;

interface

uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
XSuperJSON, XSuperObject, MultiDetailAppearanceU, FMX.Graphics, FMX.Objects;

type
   TMyThread = class(TThread)
   private
      procedure UpdateMainThread;
   protected
      procedure Execute; override;
   public
   Sonuc: String;
      constructor Create(Suspended: Boolean);
   end;


implementation




uses Unit1, Unit3, FMX.ListView;

constructor TMyThread.Create(Suspended: Boolean);
begin
   Inherited Create(Suspended);
   FreeOnTerminate := True;
end;


procedure TMyThread.Execute;
var
  X , Obj: ISuperObject;
  J: Integer;
begin
Form1.ListView1.Items.Clear;

 X := TSuperObject.Create(Form1.IdHTTP1.Get('http://site.com/?~/az/api/kateqori/'));


    with X.A['tipler'] do
    for J := 0 to Length -1 do
    begin
      Obj := O[J];
    begin

  Sonuc:=Obj.S['name']+' ('+Obj.I['count'].ToString+')';
   Synchronize(UpdateMainThread);
    end;

    end;

end;




procedure TMyThread.UpdateMainThread;
var
LItem: TListViewItem;
begin
LItem:=Form1.ListView1.Items.Add;
LItem.Text:=Sonuc;
end;

Kod: Tümünü seç

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.ListView.Types, FMX.StdCtrls, FMX.ListView, Unit2, IdBaseComponent,
  IdComponent, IdTCPConnection, IdTCPClient, IdHTTP;

type
  TForm1 = class(TForm)
    ToolBar1: TToolBar;
    ListView1: TListView;
    Button1: TButton;
    IdHTTP1: TIdHTTP;
    procedure Button1Click(Sender: TObject);
    procedure ListView1ItemClick(const Sender: TObject;
      const AItem: TListViewItem);
  private
   CountingThread: TMyThread;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}


procedure TForm1.Button1Click(Sender: TObject);
begin

   CountingThread := TMyThread.Create(True);
   CountingThread.Resume;
end;
Burdaki Thread biraz farklı gibi gözüküyor ama tam olarak doğrumu yalnışmı bilemiyorum.
Bu kodların doğruluğunu yada yanlışlığnı sölemenizi isterim..

Sizin verdiyiniz örnek üzere neden kod yazmadığıma gelince sorduğum sorularda cevaplarınızı tam olarak anlayamadım.
En önemlisi bir Thread İD-sini nasıl değişken olarak ekleyip döngü içinde kullanacağımıda..

Tıklam içinde oluşturduğum kanallara gelince dediyiniz gibi 100 kanal oluşturma gibi bir niyetim yok.
Orda yazdığnız 100 kanal satrını bir misal olduğunu anladım.

Şöle sölemek gerekirse
KX := TSuperObject.Create(Form1.IdHTTP1.Get('http://site.com/?~/az/api/cat/'+X.A['tipler'].O[Form1.ListView1.ItemIndex].I['id'].ToString+'/0/5'));
Dikkat ederseniz linkin sonundaki "/0/5/" bana 5 ileti getirir..
Yani kanal sınırım her zaman 5 tanedir. Ama sayfayı yüklediyimde aynı sorgu şu şekilde geder "/5/5"..

Aslında benim yapmaya çalıştığım işlemi hızlandırmaktı ama galiba işin içinden çıkamadım..
Java tarafında yazılan programı her hangi bir android cihazına yüklediğimizde bir tıklamada 300 kayıtı bir saniye içinde gözler önüne seriyor.
Bu kayıt sayısı için resimlerde geçerlidir ki bende bu hıza şaşırıyorum.

Deyerli vaktinizi ayırıp cevaplar yazdığınız ve yardımlarınız için çok minnetdarım Muharrem abi..
Azerbaycandan Sevgilerimle..
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Döngü yerine Thread.

Mesaj gönderen mrmarman »

@RADCoder yazdı:Sizin verdiyiniz örnek üzere neden kod yazmadığıma gelince sorduğum sorularda cevaplarınızı tam olarak anlayamadım.
En önemlisi bir Thread İD-sini nasıl değişken olarak ekleyip döngü içinde kullanacağımıda..

Tıklam içinde oluşturduğum kanallara gelince dediyiniz gibi 100 kanal oluşturma gibi bir niyetim yok.
Orda yazdığnız 100 kanal satrını bir misal olduğunu anladım.

Şöle sölemek gerekirse
KX := TSuperObject.Create(Form1.IdHTTP1.Get('http://site.com/?~/az/api/cat/'+X.A['tipler'].O[Form1.ListView1.ItemIndex].I['id'].ToString+'/0/5'));
Dikkat ederseniz linkin sonundaki "/0/5/" bana 5 ileti getirir..
Yani kanal sınırım her zaman 5 tanedir. Ama sayfayı yüklediyimde aynı sorgu şu şekilde geder "/5/5"..
En sonda başlayayım. Demişsin ya 300 kaydı birkaç saniyede ekrana yansıtıyor. cache mantığı kurarsan senin de öyle olur. Gelecek veri bir önceki seansta indirilmiş ise sadece tarih/saat karşılaştırması yaparak eski veriyi hop diye ekrana yansıtırsın. İndirme yapmazsın.


(1) Her ListItem bağımsız bie Thread ile download edilecek değil mi ? Bu demek ki her biri bağımsız birer thread olacak.
(2) Şimdi (A) ListItem'ine ait Thread'inin iş bitiminde sonuç değerlerinin (A) ListItem'ine yazılması lazım. Siz bir Thread'e "sen (A) ListItem'ine aitsin diyebilmek için (A) ListItemine create edilen Thread'in ID'sini yazacaksın ki, eşleştirebilesin. Yoksa elinde veriyle kala kalırsın. Thread bu veriyi nereye yazacağını nereden bilsin ? Değil mi...
(3) 100 kanal dediğim misaldi. Altını çizmek istediğim asıl nokta, çok fazla thread çok iyi anlamına gelmiyor olması.
(4) Sana 5 adet ileti mi getirecek yoksa 5 iletinin daha sonra ayrı ayrı download edeceğin 5 adet linkini mi getirecek. Direkt 5 adet tüm veri geliyorsa zaten bu tüm veri geliyor demektir. Diyecek bir şeyim kalmıyor.

- Senin yapman gereken iş TSuperObject'in blok olarak getirirken yavaş olduğundan yola çıkarak; hepsini bir kerede değil de, her birini farklı threadlerde alacak şekilde, yani birer birer çağırmak şeklinde kurgulamandır.

- Çünkü TSuperObject yapısına bakarsan kendi bünyesinde iç içe döngüler kurarak bunları ard arda download ederek getiriyor. Bu da performans düşüşü olarak sana yansıyor.

- Daha basit bir şekilde açıklamak gerekirse:
- (5) adet dediğin içerik farzı misal (10 MB) download edilecek veri uzunluğunda. Sen TSuperObject ile standart yolla bahsettiğin şekilde çağırdığından bu (10 mb)'lık tüm veri inene kadar projen bekler kalır.

- Aksi halde sen bu (5) tane her bir veriyi bağımsız birer threadler zinciri halinde örneğimize göre ortalama (2 MB)'lık dilimlerle alırsan. Önce biteni hemen ekrana / forma yansıtma imkanın olur.

- Böylece kullanıcı daha akıcı bir senaryo ile karşı karşıyadır ve mutlu olur. Toplam süren aynı olsa da kullanıcı dostu bir durum vardır. :idea:

Senin örneğindeki thread işte budur. İmzamdaki ilüzyonun kendisidir. Toplam bekleme aynı bile olsa, daha hızlı gibi algı yaratır. :bravo:
Resim
Resim ....Resim
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Döngü yerine Thread.

Mesaj gönderen thelvaci »

Aşağıdaki linkten ilgili makaleleri okuyup özümsemeye çalışmanızdan sonra aklınıza takılan sorular olursa buradan yine yardımcı olmaya çalışalım.

http://www.tugrulhelvaci.com/?tag=thread
Kullanıcı avatarı
RADCoder
Üye
Mesajlar: 129
Kayıt: 21 Ara 2013 04:03

Re: Döngü yerine Thread.

Mesaj gönderen RADCoder »

Hayırlı geceler dilerim herkese.

Muharrem abim burada her cevabınızı gördüğümde açıkçası hem utanıyor hemde size minnettar kalıyorum.
Size ne kadar teşekkür etsem azdır. Değerli zamanınızı ayırıp ta cevap yazıyorsunuz. Çok çok teşekkür ederim..

Yorumunuza baştan başlayarak cevap vermek istiyorum.
Söylediğiniz üzere cache mantığını araştıracağım. Çok mantıklı geldi, sanki uykudan uyandırdınız beni.
O konu ile ilgili araştırma yaptığımda ayrı bir konu açmayı düşünüyorum.
Düşüncem burada paylaşılan konular herkesin yararlanması acısından faydalı ola bilir.

Şimdi Konumuza dönersek benim kafamı karıştıran en önemli husus Thread ve Kanalları..
Şöyle sormak istiyorum..
1. Birden fazla sorgulama varsa birden fazla Thread-mı oluşturulmalı?
2. Yoksa Birden fazla sorgulama için Bir Thread oluşturup sorgu kadar mı kanal oluşturulmalı?
3.Oluşturduğumuz Thread-ın kanalı olmazsa doğrumu çalışır, yada bunun ne için kullanıldığının damı bir önemi var?

Şimdi olayı daha fazla uzatmadan bana küçük örnek vere bilirseniz çözüme daha çabuk ulaşacağımı zan ediyorum.
İlk olarak, Bir Thread oluşturup O Thread-ın tetiklenmesi ile ListView içinde Edit kutusuna yazdığımız sayı kadar DelphiTürkiye yazalım. Her İtem içinde bir kanal oluştursun..
Bu işlemi yapa bilen bir örnek vere bilir misiniz acaba?

Son olarak bundan önce yazdığım bir sorumda şöyle bir cevap vermiştiniz:
Senin örneğindeki thread işte budur. İmzamdaki ilüzyonun kendisidir. Toplam bekleme aynı bile olsa, daha hızlı gibi algı yaratır. :bravo:
Biliyorum belki güleceksiniz ama, yinede doğru anlayıp anlamadığımı öğrenmek istiyorum.
Verdiğim örnek doğru muydu?

Herşey için tekrar teşekkür ederim..
Cevapla