Delphi Can
Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - Baskı Önizleme

+- Delphi Can (https://www.delphican.com)
+-- Forum: Delphi (https://www.delphican.com/forumdisplay.php?fid=3)
+--- Forum: Mobil Platform - FireMonkey (FMX) (https://www.delphican.com/forumdisplay.php?fid=7)
+--- Konu Başlığı: Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme (/showthread.php?tid=4691)

Sayfalar: 1 2


Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - pro_imaj - 03-04-2020

Merhaba,

Label içindeki sayıyı görsellik olması açısında aşağıdaki thread ile 0 sayısından başlatarak ilgili sayıya kadar göstermek istiyorum.

Windows tarafında aşağıdaki şekilde istediğim oluyorken mobil tarafta uygulama kırılıyor (kapanıyor)
Bu konuda nasıl bir yöntem izlemek gerekir.

 
 TThread.CreateAnonymousThread(
   procedure()
   var
     a: integer;
   begin
     TThread.Synchronize(TThread.CurrentThread,
       procedure()

       begin

       end);
     try
       for a := 0 to StrToInt(lblBekleyen.Text) do
       begin
         Sleep(1);
         lblBekleyen.Text := a.ToString;
       end;
     finally

     end;
   end).Start;



Cvp: Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - Halil Han BADEM - 03-04-2020

(03-04-2020, Saat: 14:37)pro_imaj Adlı Kullanıcıdan Alıntı: Merhaba,

Label içindeki sayıyı görsellik olması açısında aşağıdaki thread ile 0 sayısından başlatarak ilgili sayıya kadar göstermek istiyorum.

Windows tarafında aşağıdaki şekilde istediğim oluyorken mobil tarafta uygulama kırılıyor (kapanıyor)
Bu konuda nasıl bir yöntem izlemek gerekir.

 
 TThread.CreateAnonymousThread(
   procedure()
   var
     a: integer;
   begin
     TThread.Synchronize(TThread.CurrentThread,
       procedure()

       begin

       end);
     try
       for a := 0 to StrToInt(lblBekleyen.Text) do
       begin
         Sleep(1);
         lblBekleyen.Text := a.ToString;
       end;
     finally

     end;
   end).Start;

 
procedure TForm1.Button1Click(Sender: TObject)
var
    a: integer;
begin
TThread.CreateAnonymousThread(
   procedure()
  begin
      for a := 0 to StrToInt(lblBekleyen.Text) do
      begin
        Sleep(1);
    
     TThread.Synchronize(TThread.CurrentThread,
      procedure()
      begin
         lblBekleyen.Text := a.ToString;
      end);

      end;
  end).Start;

Test etmedim. Çalışacak mı diye kontrol eder misiniz?
A değişkenini ana prosedür/fonksiyona tanımlama yapmanız daha uygun olacaktır.


Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - uparlayan - 03-04-2020

Şuna benzer bir yapı kullanabilirsiniz;

https://www.delphican.com/showthread.php?tid=4612&pid=35474#pid35474


Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - SimaWB - 03-04-2020

@pro_imaj ; kodunuzu yanlış okumadıysam lblBekleyen.Text'i Synchronize'nin dışında güncelliyorsunuz!


Cvp: Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - Fesih ARSLAN - 03-04-2020

Merhaba,
Thread içerisinden VCL bileşen özelliklerini Synchronize veya Queue ile set edebilirsiniz.
Kodunuzu aşağıdaki gibi değiştirirseniz, sorun muhtemelen çözülecektir.
  TThread.CreateAnonymousThread(
   procedure()
   var
     a, say: integer;
   begin
     say := lblBekleyen.Text.ToInteger;
     for a := 0 to say do
     begin
       TThread.Sleep(100);
       TThread.Queue(TThread.CurrentThread,
         procedure()
         begin
           lblBekleyen.Text := a.ToString;
         end);
     end;
   end).Start;



Cvp: Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - pro_imaj - 03-04-2020

(03-04-2020, Saat: 15:16)Halil Han Badem Adlı Kullanıcıdan Alıntı:
(03-04-2020, Saat: 14:37)pro_imaj Adlı Kullanıcıdan Alıntı: Merhaba,

Label içindeki sayıyı görsellik olması açısında aşağıdaki thread ile 0 sayısından başlatarak ilgili sayıya kadar göstermek istiyorum.

Windows tarafında aşağıdaki şekilde istediğim oluyorken mobil tarafta uygulama kırılıyor (kapanıyor)
Bu konuda nasıl bir yöntem izlemek gerekir.

 
 TThread.CreateAnonymousThread(
   procedure()
   var
     a: integer;
   begin
     TThread.Synchronize(TThread.CurrentThread,
       procedure()

       begin

       end);
     try
       for a := 0 to StrToInt(lblBekleyen.Text) do
       begin
         Sleep(1);
         lblBekleyen.Text := a.ToString;
       end;
     finally

     end;
   end).Start;

 
procedure TForm1.Button1Click(Sender: TObject)
var
    a: integer;
begin
TThread.CreateAnonymousThread(
   procedure()
  begin
      for a := 0 to StrToInt(lblBekleyen.Text) do
      begin
        Sleep(1);
    
     TThread.Synchronize(TThread.CurrentThread,
      procedure()
      begin
         lblBekleyen.Text := a.ToString;
      end);

      end;
  end).Start;

Test etmedim. Çalışacak mı diye kontrol eder misiniz?
A değişkenini ana prosedür/fonksiyona tanımlama yapmanız daha uygun olacaktır.

Cevap için teşekkürler.
Böyle bir kullanım desteklenmiyor.

(03-04-2020, Saat: 15:20)uparlayan Adlı Kullanıcıdan Alıntı: Şuna benzer bir yapı kullanabilirsiniz;

https://www.delphican.com/showthread.php?tid=4612&pid=35474#pid35474

Cevap için teşekkürler.
Sizin kullanımı inceliyorum.

(03-04-2020, Saat: 16:12)SimaWB Adlı Kullanıcıdan Alıntı: @pro_imaj ; kodunuzu yanlış okumadıysam lblBekleyen.Text'i Synchronize'nin dışında güncelliyorsunuz!

Cevap için teşekkürle.r
Diğer durumda işlem bitmeden sonucu göremiyorum.

(03-04-2020, Saat: 16:23)Fesih ARSLAN Adlı Kullanıcıdan Alıntı: Merhaba,
Thread içerisinden VCL bileşen özelliklerini Synchronize veya Queue ile set edebilirsiniz.
Kodunuzu aşağıdaki gibi değiştirirseniz, sorun muhtemelen çözülecektir.
  TThread.CreateAnonymousThread(
   procedure()
   var
     a, say: integer;
   begin
     say := lblBekleyen.Text.ToInteger;
     for a := 0 to say do
     begin
       TThread.Sleep(100);
       TThread.Queue(TThread.CurrentThread,
         procedure()
         begin
           lblBekleyen.Text := a.ToString;
         end);
     end;
   end).Start;

Cevap için teşekkürler.
Sizin yazdığınız şekilde işlem yaparken, windows tarafında işlem bitmeden program kapatılırsa sonsuz hata mesajına düşüyor, mobilde ayrıca deneyeceğim.

*Farklı farklı uygulamaları deniyorum bu defada hataya düşmese dahi ekrana yansıyan bir şey olmuyor. Ekrana dokunduğumda veya scroll ile hareket ettiğimde label'deki verinin değiştiğini gözlemliyorum.


Cvp: Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - pro_imaj - 03-04-2020

(03-04-2020, Saat: 16:23)Fesih ARSLAN Adlı Kullanıcıdan Alıntı: Merhaba,
Thread içerisinden VCL bileşen özelliklerini Synchronize veya Queue ile set edebilirsiniz.
Kodunuzu aşağıdaki gibi değiştirirseniz, sorun muhtemelen çözülecektir.
  TThread.CreateAnonymousThread(
   procedure()
   var
     a, say: integer;
   begin
     say := lblBekleyen.Text.ToInteger;
     for a := 0 to say do
     begin
       TThread.Sleep(100);
       TThread.Queue(TThread.CurrentThread,
         procedure()
         begin
           lblBekleyen.Text := a.ToString;
         end);
     end;
   end).Start;

@Fesih ARSLAN Bu şekilde hata veya donma olmadı. Fakat ilgili sayıdan fazla yada eksik olabiliyor neden olabilir ki, çok mantıksız geldi.



Aşağıdaki  4 label için ayrı aynı bu thread yazdım.  Label'lerdeki değerler sabit olmasına rağmen ilgili thread çalıştıktan sonraki label'lerdeki ilk değerlerden farklı oluyor -+ Bu çok ilginç geldi, tekrar tekrar kontrol ettim kodlar doğru fakat sonuçlar nasıl böyle olabiliyor. 

Label.Text Değeri - Sonuç Ekranda gözüken = Fark
977 - 969 = 8
355 - 355 = 0
33313 - 33133 = 180
36577 - 36574 =  3

*Her çalıştırmada değişiyor!
*TThread.Sleep(1); olarak kullandım sayı fazla olduğu için.


Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - Tuğrul HELVACI - 04-04-2020

TThread.Queue metodunun birinci paremetresini nil vererek deneyin.


Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - Tuğrul HELVACI - 04-04-2020

Ayrıca belirtmek isterim; Android, IOS işletim sistemlerinin iç yapısını Windows'un ki kadar iyi bilmiyorum ama; onlarda da thread scheduler'ın 1 milisaniyede thread schedule edemeyeceğine inanıyorum. Çünkü bu işletim sistemleri real-time işletim sistemleri değiller. Bu nedenle Sleep(1) çağrımınız aslında 1 milisaniyeden çok daha uzun süre bekleyecektir.

Synchronize kısaca; ana thread al bu işi sen işlet, ben de işin bitmesini bekleyeyim demektir. Dolayısı ile Syncronize içinde çağıran thread'i bekleyen kod deadlock'a neden olur. Multi thread programlamanın doğasında paralellik vardır. Tüm işi ana thread'e yaptırmak istiyorsak, yeni thread'ler kullanmanın hiç bir faydası olmaz.

Queue ise kısaca; yazdığınız kodu birinci parametre ile belirtilen thread'in mesaj kuyruğuna ekler.Birinci parametrede belirttiğiniz thread çağıran thread ise (yani TThread.CurrentThread); bu durumda mesaj kuyruğu yok edilirken temizlenir. Bu halde tüm mesajlar işletilmeye fırsat bulunamamış olabilir. İlk parametrenin nil olarak geçilmesi, yapılması istenen işi ana thread'in mesaj kuyruğuna atar. Dolayısı ile her durumda zamanı gelince işletilir.

Not : TThread.Queue ile alakalı bu forumda daha önce açtığım bir konuda bu tehlikeden örnekleri ile bahsetmiştik.


Cvp: Thread içerinde for ve sleep işleminde uygulama kırılmasını önleme - pro_imaj - 05-04-2020

(04-04-2020, Saat: 23:45)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Ayrıca belirtmek isterim; Android, IOS işletim sistemlerinin iç yapısını Windows'un ki kadar iyi bilmiyorum ama; onlarda da thread scheduler'ın 1 milisaniyede thread schedule edemeyeceğine inanıyorum. Çünkü bu işletim sistemleri real-time işletim sistemleri değiller. Bu nedenle Sleep(1) çağrımınız aslında 1 milisaniyeden çok daha uzun süre bekleyecektir.

Synchonine kısaca; ana thread al bu işi sen işlet, ben de işin bitmesini bekleyeyim demektir. Dolayısı ile Syncronize içinde çağıran thread'i bekleyen kod deadlock'a neden olur. Multi thread programlamanın doğasında paralellik vardır. Tüm işi ana thread'e yaptırmak istiyorsak, yeni thread'ler kullanmanın hiç bir faydası olmaz.

Queue ise kısaca; yazdığınız kodu birinci parametre ile belirtilen thread'in mesaj kuyruğuna ekler.Birinci parametrede belirttiğiniz thread çağıran thread ise (yani TThread.CurrentThread); bu durumda mesaj kuyruğu yok edilirken temizlenir. Bu halde tüm mesajlar işletilmeye fırsat bulunamamış olabilir. İlk parametrenin nil olarak geçilmesi, yapılması istenen işi ana thread'in mesaj kuyruğuna atar. Dolayısı ile her durumda zamanı gelince işletilir.

Not : TThread.Queue ile alakalı bu forumda daha önce açtığım bir konuda bu tehlikeden örnekleri ile bahsetmiştik.

Merhaba Tuğrul hocam,

Sorun sadece mobil tarafta değil windows tarafında da oluşuyordu, sayıların +- olmasını sizin yazınızı ve gönderdiğiniz link okumadan önce anlamlandıramıyordum yani nasıl olurda farklı olurdu, hatta başka başka işlemleri yaptığımda bu fark açılıyordu.

Aşağıdaki önerdiğiniz şekilde kullanınca sorun çözülmüş oldu. Yazdığınız linki inceleyince oradaki bir cevap tamda buna işaret ediyormuş.
Alıntı:TThread.Queue metodunun birinci paremetresini nil vererek deneyin.

Teşekkür ederim, aklınıza sağlık.