Uzun Süren İşlemlerde Durum Bildirimi

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
loaded
Üye
Mesajlar: 126
Kayıt: 12 Eki 2010 09:45
Konum: Konya
İletişim:

Uzun Süren İşlemlerde Durum Bildirimi

Mesaj gönderen loaded »

Selam Arkadaşlar Cümleten Kolay Gelsin.
Yaptığım programda büyük boyutlu binary dosyalarla çalışıyorum (~400 Mb.) haliyle bunların byte byte okunması ve işlenmesi zaman alıyor.
Okuma zamanında posizyon bilgisini progressbar kullanarak görüntülüyorum.
Sorun şu ;
-Dosya okuma esnasında belirsiz zamanlarda progressbar kilitleniyor vede okuma bitimine kadar yanıt vermiyor.
-Bazende görev çubuğunda programın simgesi kaybolup yeniden geliyor. Bu da bazı form olaylarının istem dışı çalışmasına sebeb oluyor.
Çözüm aşamasında;
1-Progressbarı update ediyorum bu bazen işe yarıyor bazen yaramıyor.
2-Application.processmessages komutu istediğim sonucu veriyor fakat bu seferde işlem süresinde afaki uzamalara sebeb oluyor.

Yoğun işlem aşamasında, bunların dışında, programa nefes aldırabilecek başka bir yöntem var mıdır ?
Bu konuda yardım ;)
Kalk ve işe yarar bir şey yap! Çünkü Allah (c.c.) yeniden başlayanların yardımcısıdır.
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Uzun Süren İşlemlerde Durum Bildirimi

Mesaj gönderen thelvaci »

loaded yazdı:Selam Arkadaşlar Cümleten Kolay Gelsin.
Yaptığım programda büyük boyutlu binary dosyalarla çalışıyorum (~400 Mb.) haliyle bunların byte byte okunması ve işlenmesi zaman alıyor.
Okuma zamanında posizyon bilgisini progressbar kullanarak görüntülüyorum.
Sorun şu ;
-Dosya okuma esnasında belirsiz zamanlarda progressbar kilitleniyor vede okuma bitimine kadar yanıt vermiyor.
-Bazende görev çubuğunda programın simgesi kaybolup yeniden geliyor. Bu da bazı form olaylarının istem dışı çalışmasına sebeb oluyor.
Çözüm aşamasında;
1-Progressbarı update ediyorum bu bazen işe yarıyor bazen yaramıyor.
2-Application.processmessages komutu istediğim sonucu veriyor fakat bu seferde işlem süresinde afaki uzamalara sebeb oluyor.

Yoğun işlem aşamasında, bunların dışında, programa nefes aldırabilecek başka bir yöntem var mıdır ?
Bu konuda yardım ;)
Uygulamanın main thread'in de uzun süren işlemler yaptığınızda 5 sn sonra; uygulamanız yanıt vermiyor durumuna düşecektir. Bu işletim sisteminin doğal davranışı. Bu tarz durumların oluşmasına mani olmak istiyor iseniz; ilgili işlemi bir başka thread vasıtası ile yapmalısınız. Ancak, thread senkronizasyonları kavramına da aşina olmalısınız. Ayrıca büyük dosyalar ile çalışır iken, CreateFileMapping API'si ile çalışmanız ciddi bir performans kazanımı sağlayabilir.
Kullanıcı avatarı
loaded
Üye
Mesajlar: 126
Kayıt: 12 Eki 2010 09:45
Konum: Konya
İletişim:

Re: Uzun Süren İşlemlerde Durum Bildirimi

Mesaj gönderen loaded »

Tuğrul Bey ilginiz ve geri dönüşünüz için çok teşekkür ederim.
İlginç olan şu ki ; Yanıt vermeme durumu her zaman aynı değil bazen 3 dakika boyunca sorun yokken bazen dediğiniz gibi 5 saniyede oluşuyor.
Thread konusunu ile ilgili olarak öncelerde çok araştırma yaptım hatta başlangıç noktam sayfanız olmuştu. (Özellikle Paralel Programlama)
Konu ile ilgili yaptığım denemelerde thread mevzusunun da kendi çapında çıkmazları olduğunu gördüm. Çalışma esnasında form nesnelerinin kontrolleri konusunda sıkıntılar yaşamam sebebiyle bu yöntemden vazgeçmiştim.(Yada ben beceremedim)
Çünki 4 çekirdekli bir işlemcide program yanıt vermeme aşamasına düştüğünde işlemcinin çalışma yüzdesi %25 ti.
Yani geriye kalan %75 lik kısmın yarısını bile programa tahsis edebilseydim istediğimi direk elde etmiş olacaktım.
Kalk ve işe yarar bir şey yap! Çünkü Allah (c.c.) yeniden başlayanların yardımcısıdır.
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Uzun Süren İşlemlerde Durum Bildirimi

Mesaj gönderen thelvaci »

loaded yazdı:Tuğrul Bey ilginiz ve geri dönüşünüz için çok teşekkür ederim.
İlginç olan şu ki ; Yanıt vermeme durumu her zaman aynı değil bazen 3 dakika boyunca sorun yokken bazen dediğiniz gibi 5 saniyede oluşuyor.
Thread konusunu ile ilgili olarak öncelerde çok araştırma yaptım hatta başlangıç noktam sayfanız olmuştu. (Özellikle Paralel Programlama)
Konu ile ilgili yaptığım denemelerde thread mevzusunun da kendi çapında çıkmazları olduğunu gördüm. Çalışma esnasında form nesnelerinin kontrolleri konusunda sıkıntılar yaşamam sebebiyle bu yöntemden vazgeçmiştim.(Yada ben beceremedim)
Çünki 4 çekirdekli bir işlemcide program yanıt vermeme aşamasına düştüğünde işlemcinin çalışma yüzdesi %25 ti.
Yani geriye kalan %75 lik kısmın yarısını bile programa tahsis edebilseydim istediğimi direk elde etmiş olacaktım.

Paralel programlama iyidir hoştur ancak dikkat edilesi bazı ufak tefek noktaları vardır; onlara yeterince özen gösterir iseniz eğer; yaşadığınız sıkıntıları aşabileceğinize inanıyorum. Öncelikle, makalelerimi okudu iseniz thread'ler hususunda; VCL'in thread güvenlikli olmadığını biliyor olmalısınız. Herhangi bir thread içinden ortak kullanılan alanlara erişim hususunda son derece dikkatli olmanız icap eder. Aksi durumda; beklenmeyen neticeler almanız son derece olasıdır.

Uygulamanızın main thread'i zaman zaman yanıt vermez durumda oluyor ise ve yapılan iş aşağı yukarı aynı zaman diliminde tamamlanıyor ise yine görünmeyen/gizli bir sorununuz var demektir. Bu cümlenizden çıkarttığım kadarı ile zaman zaman uygulamanızın ana thread'inin mesaj kuyruğu işleme giriyor(Application.ProcessMessage->GetMessage->TranslateMessage->DispatchMessage); zaman zaman da girmiyor demektir. Mesajları mesaj kuyruğundan alıp almama koşulunuzu uygulamanız içinde incelemenizi öneririm. Aksi taktirde yapılan iş hep aynı sürede oluyor ise; aynı şekilde her daim uygulamanızın yanıt vermiyor durumuna geçmesi gerekir idi.

Şu aşamadan sonra mevcut kodlarınızı thread programlama ile değiştirme cihetine gidecekseniz eğer; nacizane tavsiye olarak ilk aşamada; işlemcinizde kaç çekirdek var ise çekirdek sayısı * 2 kadar thread create etmenizi öneririm en fazla. Ardından da VCL ile haberleşecek ise thread'leriniz bu haberleşme kodunuzu TThread.Queue ile sarmalamanızı öneririm.

TThread.Synchronize metodunu da kullanabilirsiniz ama, bu beklenmeyen deadlock'lar ile karşılaşmanıza neden olabilir. Örneğin; uygulamanızın ana thread'i herhangi bir kernel nesnesini bekliyor ise (WaitForSingle/MultipleObjects vb) ve ilgili kernel nesnesini signaled duruma sokacak olan thread'de uygulamanın main thread'inde çalışması için bir TThread.Synchronize çağrımı gerçekleştirir ise işte tam bu noktada uygulamanız kilitlenecektir. Çünkü ana thread x thread'inin kullandığı bir kernel nesnesini bekler iken, kernel nesnesi ile işlem yapan thread'de ana thread'e: "al şu kodu çalıştır" demiştir. Main thread blocking durumda olduğu için, ilgili emri yerine getiremez; bu emri veren thread'e ilgili emrin yerine gelmesini beklediği için asla bir sonraki satırı(kernel nesnesini signaled duruma sokan kodu) işletemez ve karşınızda nur topu gibi bir DEADLOCK!

Threading dediğim gibi iyidir, hoştur lâkin tasarımın iyi olması ve thread'ler arası haberleşmede kullanıcak senk. nesnelerinin ve bu yapıların dikkat ile kullanılması gerekir.
Kullanıcı avatarı
loaded
Üye
Mesajlar: 126
Kayıt: 12 Eki 2010 09:45
Konum: Konya
İletişim:

Re: Uzun Süren İşlemlerde Durum Bildirimi

Mesaj gönderen loaded »

Tuğrul Bey vakit ayırıp bu değerli açıklamaları yapmanız hasebiyle size minnettarım çok teşekkür ederim.
Kalk ve işe yarar bir şey yap! Çünkü Allah (c.c.) yeniden başlayanların yardımcısıdır.
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3081
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Re: Uzun Süren İşlemlerde Durum Bildirimi

Mesaj gönderen sabanakman »

Eğer, bu kodlar tek akış yoluyla çalışacak ise döngü içindeki Application.ProcessMessages sayısını düşürmek az biraz işe yarayabilir :mrgreen: .

Kod: Tümünü seç

var t:Cardinal;
begin
  t:=0;
  while not ADOQuery1.Eof do begin
    //...
    if t<GetTickCount then begin
      Application.ProcessMessages;
      t:=GetTickCount+500;//0.5 sn periyotla tazele
    end;
    ADOQuery1.Next;
  end;
end;
Tavsiye edebileceğim başka bir yöntem ise, bu kodları bir kanal yoluyla arka plana atıp orada çalıştırmak. Bunu otomatik olarak yapacak basit bir makale hazırlamıştım. Tabi burada kanal kullanıldı ama kullanım amacı kanal olmaktan ziyade, yoğun süren kod bloğunu arka plana atıp bitmesini beklerken arayüzün kilitlenmemesini sağlamaktan ibarettir. Örnekteki Aralik özelliği 50 olmuş, bunu 500 yapmak faydalı olabilir. İyi çalışmalar.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Kullanıcı avatarı
loaded
Üye
Mesajlar: 126
Kayıt: 12 Eki 2010 09:45
Konum: Konya
İletişim:

Re: Uzun Süren İşlemlerde Durum Bildirimi

Mesaj gönderen loaded »

Şaban Bey ehemmiyetli makaleniz vede değerli vaktinizi ayırıp cevap verdiğiniz için çok teşekkür ederim.
Kalk ve işe yarar bir şey yap! Çünkü Allah (c.c.) yeniden başlayanların yardımcısıdır.
Cevapla