Ornekteki kodun sakincasi varmi?

Başlatan bunalmis, 11 Ocak 2010, 19:18:42

z

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
        for i:=0 to 1000 do
            begin
               form1.caption:=inttostr(i);
               refresh;
               application.ProcessMessages;
            end;
end;


Bu kodu calistirip procedure gorevi tamamlanmadan tekrar tekrar Button1 tiklanmasinin stack acisindan herhangi bir sakincasi varmi?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

birumher

Stack açısından sakıncası yok. Zaten main thred içinde işlem yapıldığı için birbirlerinin içinde çalışmıyor birbirlerini bekliyorlar...
Birkan.Herguner

Klein

stack açısından sakıncası yok. Ancak rutin işlerken kullanıcı butona bastığında ekran tazalenmez, kullanıcı butona basmadığını düşünerek  fazladan basabilir.  
İşlem başladığında  butonu disable edip, bittiğinde enable etmek daha doğru bir yaklaşım olur.

z

Stack acisindan sakincasinin olmadigini neye dayanarak soyluyoruz.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Klein

hocam  butona bastığınızda ,  butanclick mesajı mesaj kuyruğuna  ekleniyor. eğer bir önceki mesaja konu olan rutinin işlenmesi bitmediyse ,  bir sonraki mesaj  işlenmiyor.  Bu yüzden stack sorunu olmuyor.  Ancak mesaj kuyruğu şişebilir , ama onun da üç beş buton mesajıyla şişecek bir kuyruk olduğunu hiç sanmıyorum.

wsxwsx

toplam 1001 kere                
              application.ProcessMessages çalışıyıor, biriken mesajlar işleniyor. Stack kesin şişmez.   uygulama parıl parıl olur. uygulama butona saygıda kusur etmemek için ne gerekiyorsa yapar.  

fakat bu kodun çalışabilmesi için öncelikle bu olayın tetiklenebilmesi lazım. diğer işlerden fırsat bulabilirse müsait br zaman tetiklenebilir.  :)

Klein

@wsxwsx
başka bir başlıkta bu konu tartışılmıştı.  evet yaklaşım doğru değil. Döngü olmamalı bunlar konusunda herkes hemfikir.

Ama sizin bu konudaki yaklaşımınız da oldukça abartılı.

1001 kez application.processmessage çağırılmış da ne olmuş yani. neye zaman bulamamış windows.

programı 1sn kadar durdurabilmek için

1.000.000.000 x 1.000.000.000 x 1.000.000.000 x 1.000.000.000 kez application.processmessage ve refresh çalıştırmak zorunda kaldım.

1.000.000.000 'lık  içiçe 4 döngü yapmam gerekti maknayı 1sn durdurabilmek için.

Aşağıdaki kodu çalıştırıp peş peşe 100 kez butona basıyorum.  btncnt yaklaşık 1.5 saniyede bir artıyor.  aynı zamanda arkada internet explorer penceresinde de flash animasyon oynuyor kesintisiz.  
procedure TForm1.Button2Click(Sender: TObject);
var i,z,t,k:integer;
begin
  bcnt := bcnt+1;
  caption:=inttostr(bcnt);
  for i:=0  to 1000000000 do;
  begin
       for z:=0 to 1000000000 do;
       begin
          for t:=0 to 1000000000 do;
          begin
              for k:=0 to 1000000000 do;
              begin
                label3.Caption:=inttostr(k);
                refresh;
                application.ProcessMessages;
              end;
              label2.Caption:=inttostr(t);
              refresh;
              application.ProcessMessages;
          end;
          label1.Caption:=inttostr(z);
          refresh;
          application.ProcessMessages;
       end;
       label5.Caption:=inttostr(i);
       refresh;
       application.ProcessMessages;
  end;
end;

wsxwsx

internet explorer çalışır. çünkü o ayrı bir uygulama. burada sorun olan aynı uygulama içinde yapılacak yapılması istenen diğer işlemlerin aksaması.

z

Alıntı Yap...Fakat bu kodun çalışabilmesi için öncelikle bu olayın tetiklenebilmesi lazım. diğer işlerden fırsat bulabilirse müsait br zaman tetiklenebilir.

Burda cevaplanmasi gereken onemli bir durum var.

Bir procedure baslatiliyor ve kodlarin tamami bitirilmeden applicationprocessmessages ile windowsa benim isim bitmedi ama biraz da sen devam et diyoruz.

Diyelimki procedure basladiktan itibaren app..proc..mes.. isleninceye kadar milyonlarca istek kuyruga girdi.

App..proc.mes. ile windowsa buyur birazda diger isteklere bak dedigimizde windows, kuyruktaki isteklerin tamamini isleyip te mi procedurde kalinan yere geri geliyor. Windowsun buradaki stratejisi nedir?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Klein

Alıntı yapılan: "wsxwsx"internet explorer çalışır. çünkü o ayrı bir uygulama. burada sorun olan aynı uygulama içinde yapılacak yapılması istenen diğer işlemlerin aksaması.
Evet ben de bundan bahsediyorum işte.  Kodu yazan bensem , uygulamam bir rutini çalıştırırken başka bir işlem yapamıyorsa ve benim o işlemi kesin yapmam gerekiyorsa , zatem kodu öyle yazmam. eğer öyle bir kod yazıyorsam bunu göze alıyorum demektir.

Bukonudaki son sözüm şu:
Bu tip bir yazım OOP felsefesine aykırı. Yazılmasa iyi olur . Ama böyle yazılırsa da  da kıyamet kopmaz.

@bunalmis hocam
Windows'un mesaj işleme öncelikleri vs.. hakkında çok derin bilgi sahibi değilim.  
Ama şunu tecrübe ve gözlemlerime dayanarak söyleyebilirim.  evet sizin uygulamanızın kuyruğundaki işlenmesi uygun olan tüm mesajları işliyor. Örneğin mesaj kuyruğunda buton için 10 tane mesaj var ve hepsi onclick olayına ait mesajlar. Bu durumda sizin onclick olayınız halen tamamlanmadığı için bu mesajlar işlenmiyor.  

Ama mesaj trafiği üzerinde düşünürken şunu da dikkate almak gerek:
Örneğin mouse hareketi var. Mouse mesajı kuyruğa peşpeşe eklenmez. en son mouse konumu ne ise   , farenin yeni konumu bunun üzerine yazılır. Bu durumda sadece 1 fare mesajı işlenmiş olur. Aynı şekilde ekran tazeleme  mesajları , zamanlayıcı mesajları gibi birçok mesaj kuyrukta 1 kez yer alır ve yeni gelen mesaj bunun üzerine yazılır.

wsxwsx

Alıntı yapılan: "bunalmis"App..proc.mes. ile windowsa buyur birazda diger isteklere bak dedigimizde windows, kuyruktaki isteklerin tamamini isleyip te mi procedurde kalinan yere geri geliyor. Windowsun buradaki stratejisi nedir?
App..proc.mes. dediğiniz yerde , program kendisine windows tarafından gönderilen tüm biriken mesajları işler ve bitirir.

Normalde ise bunu yazmasak bile galiba müsait bir zaman karar vererek mesajları işliyor. Galiba bu durum OnIdle olayında gerçekleşiyor . Programın kendisine windows tatafından gönderilen mesajlar ise OnMessage olayı ile yakalanıyor.

İstersek bu 2 durumu kendimiz değerlendirebilirmişiz.

form üzerine ApplicationEvents nesnesinden 1 adet yerleştirerek artık bu olayları yakalayabiliriz.

procedure TForm1.ApplicationEvents1Idle(Sender: TObject;
 var Done: Boolean);
begin

end;

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
 var Handled: Boolean);
begin

end;

z

Bir procedure icinde kodlarimiz kosarken forum uzerindeki bir butonun clicklenip clicklenmedigini anlayabilirmiyiz?

Tabiki app..pro..mess. kullanmadan.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

wsxwsx

hehe olmaz öyle şey. thread kullanmalisin.
çünkü o sırada butonun basilamaz. şekilde gorülmektedir.
durumu göstermek icin ornek yaptim:
http://www.speedyshare.com/files/20364230/deneme.zip

en klas makineniz de olsa çalışmaz.  ister 2çekirdekli makine de dene ister 4.
ne hikmetse ktunnel içinden bu zip tıkalanamıyor. ayrı sayfaya yapıştırın

http://www.speedyshare.com/files/20364230/deneme.zip



procedure TForm1.Button1Click(Sender: TObject);
begin
  while true do
  begin
    sayi := sayi  + 1;

    if durum then
      break;
  end;
  MessageDlg('sayma bitti !', mtInformation, [mbOK], 0);

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  durum := true
end;

z

Olur olmasina da ince bir soru bu. Cevabi da inceliklidir.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

wsxwsx

olmaz , çünü program döngü içine çakılıp kalmıştır. saniyede binlerce kere oluşan diğer olayların hiç biri gerçekleşmez. programın arada sırada fare konumu, buton konumu gibi konuları dolaşıp gelmesi gerek. bunların hepsi döngü sebebiyle aksamakta. Hatta binlerce kere paint olayı mı ne oluşuyor. formun herbir noktası yeniden çiziliyor. OnDragDrop  gibi bazı olaylar da var. bunların tamamı aksamış oluyor. çünkü formunkendisi tek bir thread olarak çalışıyor.