Uzun süren işlemlerde program kilitlenmesin

Yazdığınız makaleleri ve üyelerimizin işine yarayacağını düşündüğünüz kodlarınızı gönderebilirsiniz. Bu foruma soru sormayın!
Cevapla
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 2977
Kayıt: 17 Nis 2006 07:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Uzun süren işlemlerde program kilitlenmesin

Mesaj gönderen sabanakman » 06 Mar 2015 04:59

İyi günler. Fark ettiğim kadarıyla bu arada sırada sorulan bir sorudur. Çok uzun süren bir işlem veya sorgunun bitmesini beklerken proje tepki vermez hale gelir ve bunu kullanıcı dostu bir arayüz haline nasıl getirilmesi gerektiği sık sık sorulur ve genel olarak verilen cevaplarda kanal (thread) kullanarak nasıl aşılacağı tarif edilir. Bu makalede ise bu durumu daha da hazır hale getiren basit bir kütüphane sunulmaktadır. Örnek proje xe5 üzerinde yazıldı ve bir .giff animasyonu oynatmaktadır. Burada asıl olan "untArkaPlan.pas" dosyası ve burada tanımlı "TArkaplandaYap" sınıfıdır. Bu sınıf daha eski Delphi sürümlerinde de kullanılabilir. Yöntem aslında basit, işlemi uzun süren olay (TNotifyEvent) veya prosedürün kanal (TThread) kullanılarak arka planda çalıştırılıp bitmesini beklemekten geçiyor. Tabi bu bekleme projemizin VCL ara yüzünü kilitlenmesini engelleyen ara ara (örneğe göre 50 ms. de bir) "Application.ProcessesMessage" kodunu çalıştırmaktadır. Bu sayede ekranda kullanıcıya sunulan bekleme animasyonu oynatılacak ve bu animasyon da kilitlenmeden asıl işimizin aynı anda geri planda çalışıyor olmasıyla işlem tamamlanacaktır. Burada, arka plana çalışması için gönderilen kodlamalarda bazı noktalara dikkat etmek gerekiyor.
-Arka planda çalışacak kodların, VCL arayüzüne direkt müdahale etmiyor olması gerekmektedir. Malum, VCL'de kanal desteği bulunmamaktadır.
-Eğer DataSet temelli kayıtlar üreten sorgu açılacaksa sorguyu açmadan önce DisableControls ile VCL bağlantısı kesilmeli ve sonunda da tekrar EnableControls ile eski haline alınmalı.
-Arka planda çalıştırılacak işlemlerin içinde diyalog pencereleri olmaması daha sağlıklı olacaktır. Bunun yerine arka planda iş bittikten sonra ana program kanalında diyalog gösterilmeli.
-Bu yöntem kullanılacağı zaman şahsi tavsiyem, ekranı kaplayan bir panel veya form içinde animasyon gösterilmeli ve projede işlem yapılamayacak bir şekle getirilmeli.

İşlemi arka planda çalıştırmak için aşağıdaki gibi kodlarla çağırmak mümkündür. Bu çalıştırılan işlemler hem farklı bir kanaldan yürütülecek hem de bitene kadar bekleniyor olacaktır. İşin püf noktası bu bekleme esnasında programın kilitlenmiyor olmasıdır.

Kod: Tümünü seç

procedure TForm1.Button1Click(Sender: TObject);
begin
...
end;

procedure TForm1.Prosedur;
begin
...
end;
...
...
...
Arkaplanda.Calistir(Button1Click, Button1);
Arkaplanda.Calistir(Prosedur);

Kod: Tümünü seç

raise ASonuc.HataSinifi.Create(ASonuc.HataMesaji);
Ayrıca arka plana atılan bir iş eğer bir istisna (Exception) çıkarmışsa bu bileşen çıkan istisnayı aynı şekilde taklit ederek ana kanala bu istisnayı gönderdiği için hata yakalama konusunda çok farklı yollara gitmeye gerek kalmamaktadır.

Kod: Tümünü seç

try
  Arkaplanda.Calistir(Prosedur);
except
  on E:Exception do begin
    ShowMessage(E.Message);
  end;
end;
Ekte XE5 ile yapılmış örnek proje bulunmaktadır. Bu örnekte ikiSaniyeislemYap ve SorguAc prosedürleri tanımlıdır. Bu işlemleri hem direkt çalıştıran hem de arka planda çalıştırıp bitme süresini ekranda gösteren butonlar bulunmaktadır. Tabi direkt çalıştırıldıkları zaman animasyon donuyor ama arka planda yürütüldüklerinde ise animasyonda herhangi bir takılma olmuyor. Sorgunun çalışması için ADOConnection nesnesini, Delphi ile gelen örnek "DBDEMOS.udl" bağlantısını kullanmak gerekmektedir. İyi çalışmalar.
Dosya ekleri
islemYap.7z
(101.76 KiB) 192 kere indirildi
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .

Kullanıcı avatarı
vkamadan
Kıdemli Üye
Mesajlar: 1934
Kayıt: 17 Mar 2004 03:52
Konum: Adapazarı
İletişim:

Re: Uzun süren işlemlerde program kilitlenmesin

Mesaj gönderen vkamadan » 07 Mar 2015 09:46

@sabanakman ,
Değerli paylaşımın için teşekkür ederim kullandım emeğine sağlık.
İyi çalışmalar.
Volkan KAMADAN
www.polisoft.com.tr

Kullanıcı avatarı
hi_selamlar
Üye
Mesajlar: 518
Kayıt: 05 May 2005 02:24
Konum: DelphiTürkiye.COM

Re: Uzun süren işlemlerde program kilitlenmesin

Mesaj gönderen hi_selamlar » 08 Oca 2016 05:04

S.a.
hocam çalışmanız için çok teşekkür ederim.
DB sorgu açmada DisableControls - EnabledControls işlemlerini de yapma
rağmen yinede hata veriyor.

Grid üzerinde veri listelemiyor ve hata veriyor.
Thread konusuda çok hakim değilim. Hatta hiç değilim desem yeridir.
Herkes cahildir, bazi konularda.

Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 2977
Kayıt: 17 Nis 2006 07:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Re: Uzun süren işlemlerde program kilitlenmesin

Mesaj gönderen sabanakman » 09 Oca 2016 09:10

Ne hata geliyor bilmiyorum ama DisableControls ile birlikte DataSet özelliği bu tabloya bağlı nesnelerin bağlantısını da kesip deneyin bir de.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .

Kullanıcı avatarı
hi_selamlar
Üye
Mesajlar: 518
Kayıt: 05 May 2005 02:24
Konum: DelphiTürkiye.COM

Re: Uzun süren işlemlerde program kilitlenmesin

Mesaj gönderen hi_selamlar » 12 Oca 2016 11:42

Deneyip bilgi aktarim hocam.
Teşekkürler.
Herkes cahildir, bazi konularda.

Kullanıcı avatarı
Opt2000
Üye
Mesajlar: 215
Kayıt: 09 Tem 2003 09:04

Re: Uzun süren işlemlerde program kilitlenmesin

Mesaj gönderen Opt2000 » 12 Oca 2016 06:07

Merhaba,

Veri tabanı işlemlerinde, main thread'den farklı bir thread içinde işlem yapıyorsanız, o thread için ayrı bir connection açmanız gerekiyor. Her ne kadar bazı veri tabanı sistemleri aksini iddia etse de ben bu konuda tutarlı davranan bir veri tabanı sistemi görmedim :) Belki @sabanakman'ın yazdığı thread helper (ne diyeceğimi bilemediğim için böyle isimlendirdim) "veri tabanı işlemlerinde aynı anda sadece bir işlem yapılacak, bu sırada kullanıcı bekletilecek ve program da Not Responding durumuna düşmeyecek" manifestosuyla kullanılabilir. Burada bile "DisableControls, BeginUpdate" vs gibi bir sürü şeye dikkat etmek gerekecek.

Sonuç olarak:
1. Öncelikle @thelvaci'nın thread'ler konusunda çok güzel yazıları var. Onları mutlaka okuyun. Ve mümkünse her yazıyı okuduktan sonra ara verin, bir iki gün bekleyin ve yazıyı tekrar okuyun. Yani hepsini bir seferde okumayın. Bütün sistemin kafanızda yer etmesi için gerekli zamanı tanıyın. O zaman @sabanakman'in hazırladığı sınıfı çok daha verimli (ve aslında doğru) kullanacaksınız.

2. Veri tabanı işlemlerinde her thread için bir connection açın (özellikle veri tabanı sisteminiz desteklemediğini açık açık söylüyorsa. Örneğin bildiğim kadarıyla SQL Server desteklemiyor).

İyi çalışmalar

jakarta2
Üye
Mesajlar: 58
Kayıt: 20 Nis 2015 05:51
İletişim:

Re: Uzun süren işlemlerde program kilitlenmesin

Mesaj gönderen jakarta2 » 05 Eki 2016 03:29

Merhaba;

Uygulamayı çalıştırdım çok güzel :bravo: :bravo: :bravo:

Fakat bu sadece vcl için bunun firemonkey için olanını nasıl uygulayacağız?
Tarkaplandayap componentini tanımıyor...

Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 2977
Kayıt: 17 Nis 2006 07:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Re: Uzun süren işlemlerde program kilitlenmesin

Mesaj gönderen sabanakman » 01 Ara 2016 02:07

untArkaPlan.pas dosyasında uses satırında bulunan "Forms" u, "FMX.Forms" olarak değiştirince çalışması lazım.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .

Cevapla