Application.ProcessMessages ve Thread Kullanımı

FireMonkey ve Mobil uygulama (iOS, Android, Windows Phone) ile ilgili sorularınızı bu foruma sorabilirsiniz.
Cevapla
siyamali
Üye
Mesajlar: 10
Kayıt: 27 Nis 2005 03:00

Application.ProcessMessages ve Thread Kullanımı

Mesaj gönderen siyamali »

Merhabalar.
Bir veritabanındaki tablodan diğerine Android üzerinden veri transfer etme işleminde progressbar tarzı pir grafik kullanmak istiyorum.
Bir türlü yapamadım. Yardımlarınızı beklerim.

Kod: Tümünü seç

   df.cari.first;
           TThread.CreateAnonymousThread(procedure
           var
           a:byte;
           begin

              repeat
                for a := 1 to 10 do g[a]:='';

                g[1]:=''''+trim(df.cariCARI_KODU.Value)+''',';
                g[2]:=''''+trim(df.cariADS.Value)+''',';
                g[3]:=''''+copy(trim(df.cariVEDAR.Value),1,40)+''',';
                g[4]:=''''+trim(df.cariVERNO.Value)+''',';
                g[5]:=''''+trim(df.cariTEL.Value)+''',';
                g[6]:=''''+trim(df.cariKOD.Value)+''',';
                g[7]:=''''+trim(df.cariGUN.Value)+''',';
                g[8]:=inttostr(df.cariGUN_KOD.Value)+',';
                g[9]:=floattostr(df.cariLIMIT.Value);
                df.yen_car_q.sql.Clear;
                df.yen_car_q.sql.Add('insert into CARILER');
                df.yen_car_q.sql.Add('values ('+g[1]+g[2]+g[3]+g[4]+g[5]+g[6]+g[7]+g[8]+g[9]+')');
                df.yen_car_q.ExecSQL;
                df.car_dur.close;
                df.car_dur.sql.clear;
                df.car_dur.sql.add('select * from CARI_DURUM');
                df.car_dur.sql.add('where CARI_KOD = '''+trim(df.cariCARI_KODU.Value)+'''');
                df.car_dur.open;
                for a := 1 to 10 do g[a]:='';

                g[1]:=''''+trim(df.cariCARI_KODU.Value)+''',';
                g[2]:=''''+trim(df.cariADS.Value)+''',';
                g[3]:=genel.vt_noktacevir(floattostr(df.car_durbakiye.value));
                df.car_dur1.close;
                df.car_dur1.sql.clear;
                df.car_dur1.sql.add('insert into CARI_DURUM');
                df.car_dur1.sql.add('values ('+g[1]+g[2]+g[3]+')');
                df.car_dur1.execsql;

                simdi:=simdi+1;
                        TThread.Synchronize(nil , procedure
                               begin
                                  Application.ProcessMessages;
                                  TrackBar1.Value:=simdi*100/kaysay;
                                  lab.Text:='%'+inttostr(round(TrackBar1.Value));
                                  Pie1.EndAngle:=TrackBar1.value*360/100;
                                  pie1.PrepareForPaint;
                                  pie1.Repaint;
                                  sleep(50);
                               end);
              df.cari.Next;
              until df.cari.Eof;
           end).Start;
ertank
Kıdemli Üye
Mesajlar: 1665
Kayıt: 12 Eyl 2015 12:45

Re: Application.ProcessMessages ve Thread Kullanımı

Mesaj gönderen ertank »

Merhaba,

Sorununuzu detaylı yazmamışsınız. Aldığınız bir hata var mı? Hata var ise hangi satırda hata alıyorsunuz? Hata mesajı nedir?
Hata yok ise çalışmayan nedir?

Bununla birlikte, thread içinde işlem yapıyorsunuz, tablo/sorgu nesnelerinizden bir tanesinin dahi LiveBinding ile ekranda GUI bağlantısı var ise thread işlemleriniz içinden otomatik grafik işlem yapılmaya çalışılacağı için hata oluşacaktır.

Ayrıca kulandığınız veritabanı bileşenleri "parametre" destekliyorsa ki günümüzde desteklemeyen yoktur. Aşağıdaki kodu her bir kayıt için tekrar tekrar çalıştırmak yerine...

Kod: Tümünü seç

df.yen_car_q.sql.Clear;
df.yen_car_q.sql.Add('insert into CARILER');
df.yen_car_q.sql.Add('values ('+g[1]+g[2]+g[3]+g[4]+g[5]+g[6]+g[7]+g[8]+g[9]+')');
Aşağıdaki satırı döngü dışında yazmanız

Kod: Tümünü seç

df.yen_car_q.sql.Text := 'insert into CARILER values (:1, :2, :3, :4, :5, :6, :7, :8, :9)';
Döngü içinde de aşağıdaki şekilde parametre ataması yapmanız daha sağlıklı olacaktır

Kod: Tümünü seç

df.yen_car_q.Params[0].AsString := Trim(df.cariCARI_KODU.AsString);
df.yen_car_q.Params[1].AsString := Trim(df.cariADS.AsString);
// FMX platformunda string indeksi sıfır tabanlı, Windows ortamında ise 1 tabanlı olabilir.
// SubString yardıncı fonksiyonu her zaman sıfır tabanlı çalışacağı için sorun çıkmayaaktır
df.yen_car_q.Params[2].AsString := Trim(df.cariVEDAR.AsString).SubString(0, 40); 
df.yen_car_q.Params[3].AsString := Trim(df.cariVERNO.AsString);
df.yen_car_q.Params[4].AsString := Trim(df.cariTEL.AsString);
df.yen_car_q.Params[5].AsString := Trim(df.cariKOD.AsString);
df.yen_car_q.Params[6].AsString := Trim(df.cariGUN.AsString);
df.yen_car_q.Params[7].AsInteger := df.cariGUN_KOD.AsInteger;
df.yen_car_q.Params[8].AsFloat := df.cariLIMIT.AsFloat;
df.yen_car_q.ExecSQL();
Aynı yapıyı "car_dur1" tablosu için de kullanabilirsiniz. Hatta kullanmalısınız.
1- Performans daha yüksek olacaktır
2- Hata yapma olasılığı daha düşük olacaktır.
3- "for a := 1 to 10 do g[a]:='';" koduna hiç ihtiyacınız olmayacak
4- "a" değişkenine hiç ihtiyacınız olmayacak.

Ayrıca "repeat .. until" döngüsü yerine "while not df.cari.Eof do begin .. end" döngüsü kullanmalısınız. Hiç kayıt olmadığı zaman hata alırsınız.
siyamali
Üye
Mesajlar: 10
Kayıt: 27 Nis 2005 03:00

Re: Application.ProcessMessages ve Thread Kullanımı

Mesaj gönderen siyamali »

İlginize ve verdiğiniz bilgiler için teşekkür ederim.
Sorunum progressbar olarak değerlendirelim.
Sistem tablodan kayıt okuyup diğerine yazınca progressbarın bu kayıtların sayısına göre ilerlemesini istiyorum.
thread kullanmazsam program tablo eof olana kadar kilitleniyor ve progressbas ilerlemiyor.
Thread kullandığım zamanda (doğru kullandığımdan emin değilim) ilk kaydın işlemini yapıyor ve döngüden çıkıyor.
ertank
Kıdemli Üye
Mesajlar: 1665
Kayıt: 12 Eyl 2015 12:45

Re: Application.ProcessMessages ve Thread Kullanımı

Mesaj gönderen ertank »

Paylaştığınız koda göre bir tane işlem yapıp çıkıyor ise tabloda tek kayıt olmalı.
Ayrıca kaysay değerinin doğru olduğundan emin olmanızda fayda var.
Bunun dışında adım adım F8 tuşu ile şeklinde ilerleyerek neden ilk işlemde çıktığını kontrol edebilirsiniz.
siyamali
Üye
Mesajlar: 10
Kayıt: 27 Nis 2005 03:00

Re: Application.ProcessMessages ve Thread Kullanımı

Mesaj gönderen siyamali »

Dediğiniz gibi yaptım. 150 kayıt var. Win32 de sorunsuz çalışıyor fakat androidde döngünün dışına çıkıyor.
ertank
Kıdemli Üye
Mesajlar: 1665
Kayıt: 12 Eyl 2015 12:45

Re: Application.ProcessMessages ve Thread Kullanımı

Mesaj gönderen ertank »

Android'de 150 kayıt olduğuna gerçekten emin misiniz?

Döngüden çıkma koşulu kaytıların sonuna ulaşılmış olması. Eğer ilk işleyişten sonra çıkıyor ise bir şekilde son kayıda ulaşıyor demektir.
"Application.ProcessMessages" kullanıyorsunuz. Android sistemde çalışıyor mu bilmiyorum. Eğer çalışıyor ise kuyrukta bekleyen harici bir işlem son kayda getiriyor olabilir.

Daha önce de bahsetmiştim. Thread kullanımında LiveBinding ile ekranda herhangi bir görsel nesneye işlem yaptığınız sorguların verisi / bağlı olmaması gerekli. Bundan da emin olmalısınız. İlk döngüde çıkma sebebi belki grafik arayüz erişimi sebebiyle hata alarak thread sonlanıyor şeklinde de olabilir. DEBUG modunda ve F9 ile bir telefon üzerinde hata kontrolü yapıyorsanız bunu zaten Delphi içinde görürsünüz. Tabi eğer Delphi içinde exception daha önceden gözardı (ignore) edilmemişse. Diğer taraftan FMX platformunda Delphi debug kabiliyetleri de yeterince iyi değil. Bu yüzden belki en sağlıklısı try..except içinde işlem yapıp hata varsa log dosyasına yazmak olabilir.

Kısacası klasik hata inceleme ve tespiti yapacaksınız. Özel bir durum değil.
siyamali
Üye
Mesajlar: 10
Kayıt: 27 Nis 2005 03:00

Re: Application.ProcessMessages ve Thread Kullanımı

Mesaj gönderen siyamali »

Yeni bir projede aşağıdaki gibi denemeye başladım.
Win32 de çalışan program Androidde Thread start komutunu almıyor.
Yani tthread.CreateAnonymousThread ile başlayan bloğun için içi çalışmıyor.

Kod: Tümünü seç

tthread.CreateAnonymousThread(procedure ()
begin
         try
         yen_car_q.sql.Clear;
         yen_car_q.sql.Text := 'insert into CARILER values (:0, :1, :2, :3, :4, :5, :6, :7, :8)';

              while not cari.Eof do
                begin
                yen_car_q.Params[0].AsString:=trim(cariCARI_KODU.AsString);
                yen_car_q.Params[1].AsString:=trim(cariADS.AsString);
                yen_car_q.Params[2].AsString:=copy(trim(cariVEDAR.AsString),1,40);
                yen_car_q.Params[3].AsString:=trim(cariVERNO.AsString);
                yen_car_q.Params[4].AsString:=trim(cariTEL.AsString);
                yen_car_q.Params[5].AsString:=trim(carikod.AsString);
                yen_car_q.Params[6].AsString:=trim(carigun.AsString);
                yen_car_q.Params[7].AsInteger:= cariGUN_KOD.AsInteger;
                yen_car_q.Params[8].AsFloat:=cariLIMIT.AsFloat;
                yen_car_q.ExecSQL;

                  simdi := simdi+1;
                  Application.ProcessMessages;
                  sleep(10);
                   TThread.Synchronize(nil, procedure()
                     begin

                          TrackBar1.Value:=simdi*100/kaysay;
                          lab.Text:='%'+inttostr(round(TrackBar1.Value));
                          Pie1.EndAngle:=TrackBar1.value*360/100;
                          pie1.PrepareForPaint;
                          pie1.Repaint;
                          Application.ProcessMessages;

                      end);
                cari.Next;
              end;
          finally
         end;
end).Start;
ertank
Kıdemli Üye
Mesajlar: 1665
Kayıt: 12 Eyl 2015 12:45

Re: Application.ProcessMessages ve Thread Kullanımı

Mesaj gönderen ertank »

İşe özel thread yazabilirsiniz. Hem daha kontrollü hem daha sağlıklı çalışır.
Diğer taraftan anonim thread Android içinde de çalıştığını biliyorum.

Thread içinde GUI işlemi yapmadığınıza gerçekten emin misiniz?
Çok kez sordum ancak hiç cevap yazmadınız.
LiveBinding ile ListView gibi bir nesnede sorgu verileri gösteriliyor ise o sorguları thread içinde kullanamazsınız.
siyamali
Üye
Mesajlar: 10
Kayıt: 27 Nis 2005 03:00

Re: Application.ProcessMessages ve Thread Kullanımı

Mesaj gönderen siyamali »

Dediklerinizi yaptım çalıştı. Teşekkür ederim.
Cevapla