Amacimi anlatmam kelimlerle uzun surecek. Asagidaki kodu yazdim.
Calistirdiginizda yapilmak istenen hemen anlasilacak.
Bu amac daha usturuplu gerceklestirilebilirmi?
Programdaki gotolar nasil kaldirilir?
Not: Butonlarin enable ozelligini kullanmak istemiyorum.
procedure TForm1.BASLAClick(Sender: TObject);
label Aradan_Gir,Say;
begin
if bekle_ then
begin
bekle_:=false;
goto Aradan_Gir;
end;
if i<>0 then exit;
Say: form1.caption:=inttostr(i);
refresh;
application.ProcessMessages;
Aradan_Gir:
while bekle_ do application.ProcessMessages;
i:=i+1;
if i<1000 then goto Say;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
bekle_:=false;
i:=0;
end;
procedure TForm1.BEKLEClick(Sender: TObject);
begin
Bekle_:=true;
end;
procedure TForm1.HAZIR_OLClick(Sender: TObject);
begin
if i>999 then i:=0;
end;
Yukaridaki kod hic icime sinmiyor. Bu isi nasil daha oturakli yaparim.
Acil cevaplar cok makbule gececek.
Aklıma şöyle birşey geldi:
procedure TForm1.BASLAClick(Sender: TObject);
begin
if (not bekle_) and (i<>0) then
exit;
else
bekle_:=false;
end;
repeat
begin
Form1.caption := IntToStr(i);
Refresh;
repeat
Application.ProcessMessages;
until not bekle_
i:=i+1;
end;
until i = 1000;
end;
Tek bir problem var, bekle_ = true ise caption a i yi bir arttırmadan değer yazıyor. Form1.caption := IntToStr(i); kısmı aşağı alınarak durum değiştirilebilinir.
Not: Application.ProcessMessages; satırı uzun işlemlerde programın donmasına engel olamayabilir.
Thread kullanmanızı öneririm. Delphi'nin help'inde tthread class'ını incelerseniz nasıl yapmanız gerektiğini anlayacağınızı zannediyorum. Ayrıca Delphide Demos\Threads klasörü altında çok güzel bir örnek var. Onu da inceleyin.
haklısın ama bu arkadaş bunu anlamaz. anlamak da istemiyor. daha önce en az 3-4 sefer thread konuısunu bildirmişimdir. daha zor şekilde yapmak ve uğraşmak istiyor. işlemleri görsel nesneler ile yapınca thread kullanımı daha da bir zor olur. pek de anlamı olmaz. thread kullanılacaksa , buton, caption gibi nesneler ile işin olmaz. global bazı değişkenleri değiştirirsin. görsel nesneler timer ile müsait birzaman bu global değişkene bakarak captionunu vs.değiştirir. müsait değilse işlemin yine thread içinde devam eder. görsel belirtiler uygun bir zamanda değişir. application..processmessages kullanmak çok fena birşeydir. hele while bekle_ do application.ProcessMessages dediniz mi, cpu kullanımı aşırı yükselir.
Alıntı yapılan: "wsxwsx"haklısın ama bu arkadaş bunu anlamaz. anlamak da istemiyor. daha önce en az 3-4 sefer thread konuısunu bildirmişimdir. daha zor şekilde yapmak ve uğraşmak istiyor. işlemleri görsel nesneler ile yapınca thread kullanımı daha da bir zor olur. pek de anlamı olmaz. thread kullanılacaksa , buton, caption gibi nesneler ile işin olmaz. global bazı değişkenleri değiştirirsin. görsel nesneler müsait birzaman bu global değişkene bakarak captionunu filan değiştirir. müsait değilse işlemin yine thread içinde devam eder. görsel belirtiler uygun bir zamanda değişir. applciation.processmessages kullanmak çok fena birşeydir. hele while bekle_ do application.ProcessMessages dediniz mi, cpu kullanımı aşırı yükselir.
Yukaridaki soruya cevap olacak bir ornek verirsen belki anlarim.
Application.processmessages neden CPU yukunu artiriyor anlamadim.
Bu komut sayesinde procesure yada fonksiyon icine girildiginde disarida olup biten olaylarin da ara ara cevaplanmasi icin imkan taniyoruz.
Benim fonksiyonum cagrildiginda duruma gore 1 kac saat (bazen 5 saat) fonksiyon icinden cikilamayacak.
Mevcut yapida program calistiginda bu bir kac saat isi olan fonksiyon calismaya basladiginda zaten benim baska islerle isim olmayacak pur dikkat fonskiyon icinde islemler yapilacak.
Haydi thread kullandim diyelim. Bu bana ne avantaj saglayacak?
http://www.speedyshare.com/files/20288408/demo.zip
burada prensibi anlatan bir örnek var.
Timer olayına yazılacak kod ile , thread içinde olup bitenleri dış dünyaya göstermiş oluyoruz.
procedure TForm1.Timer1Timer(Sender: TObject);
begin
label2.Caption := inttostr(th.sayac);
led.Visible := not led.Visible;
end;
thread kullanırsan o sırada formu sürükleyip başka işler de yapabileceksin. bir yandan hesap kitap yaparken başka bir yandan gelen bilgileri istifleyebileceksin. diğer taraftan başka bir thread (bekçi diyelim) acaba alet yerinde mi cihazı söküp başka bir yere takmış olabilirler mi diye onu kontrol edecek. gül gibi geçinip gidecekler. hepsi beraber çalışacak. sleep(500) yazılınca bu esnada başka işlem yapılmayacak anlamına gelmiyor. diğer threadler 500ms lik zaman ayrılmış demektir. Birde sleepEx() fonksiyonu vardır. vaktinden önce sonlandırılabilir. yani 500ms beklerken süre dolmadan bazı işlemler tamamlanırsa hemen sonlanaibliyor. threat içinde bazı olaylar tanımlamışsan sleep yazsan bile bu olaylar tetikleniyor. ancak bu olayı thread içinde oluşturduğun başka bir thread tetiklemesi gerekebilir.
yukarıdaki link bozuk galiba yeniledim.
http://www.speedyshare.com/files/20288408/demo.zip
Anladigim kadariyla PC de yazacagim program tek bir isle değil de bir kac isle ugrasacak olsaydi ve basla dedigimde uc isi de ayni zamanda baslatsaydi o zaman bu dediginiz yontem isime yarardi.
Aksi halde bu 3 isi tek ismis gibi tek fonksiyon catisi altinda toplamam gerekirdi ve program bayagi karmasik ve anlasilirligi zor olurdu.
Thread kullaninca bu 3 isi bagimsiz islermis gibi dusunup programlarini yazmak kolay ve anlasilir olurdu. (Ben bunu anladim)
Ben hala islemleri bir kac saat surecek bir uygulamayi neden thread kullanarak yapayim anlamadim.
Program calisirken telefon calar acil bir is olur programi bekletmek gerekebilir diye bir tusa basilip basilmadigini application.processmessages ile kontrol ediyorum. Basildi ise de bir dongu icinde haydi devam edelim komutunu bekliyorum. Bu esnada da windows gene diger islemlerini yapiyor.
Bunda ne gibi bir yanlislik goruyorsun anlamadim.
senin yöntemde programın donmasını önlemek için , application.processmessages kullanmak gerekir. o da yapılan işi aksatır. yavaşlatır. Hızlı bir bilgisayarın olsa dahi yavaş kalır.
Fakat ayrı bir thread kullandın diyelim. threadi sonlandırmak için yine bir buton kullanılabilir. örneğin buton basılınca global bir değişken değişir. thread döngü içinde buna bakar. gerekirse kendini sonlandırır. if son then self.terminate gibi.
eğer thread kullanırsan birkaç saat sürecek işi bilgisayar 1-2 dakikada tamamlayabilir.
Normalde ayrı uygulama açtığımızda aslında ayrı bir thread başlamış oluyor. bu yüzden bir programın donması diğerini etkilemiyor. form içinde ayrı thread kullanmadan uzun bir döngü yaparsak program donmuş olur. istenmeyen bir durumdur. gerekli yerlere application.processmessages ekleyerek vaziyeti kurtarmaya çalışırız. ancak bir döngü içinde sürekli bunu kullanırsak işler aksar. hiç olmazsa saniyede bir filan kullanılır. durum daha az kötü olur.
@bunalmis
yukarıdaki gibi bir programı başlattığınızda çalışan ilk ve tek thread "ui (user interface) thread" dir. bu thread kullanıcı ile sizin programınız arasındaki iletişimi sağlayan uygulama pencerenizi yönetir. eğer siz uzun sürecek işlemi oluşan bu ilk ui thread içine yazarsanız yaptığınız işlem süresince uygulama pencereniz kullanıcıya cevap veremeyecektir. siz bunu engellemek için application.processmessages gibi bir çözüme başvurmuşsunuz. ancak burada doğru olan uzun sürecek işlemlerin, işlem çok basit dahi olsa ui thread den bağımsız olarak ayrı bir thread de yapılmasıdır. konu başlığında bahsettiğiniz "işi bilenler" bu şekilde yapmaktadırlar.
Uygulamamda isin 5 saat gibi uzamasina neden olan durum yazilim değil kumanda edilen mekanik cihazin yavas olmasi.
Fonksiyon icine bir girildimi saatlerce calisiyorsa zaten hangi kodu isletirsek isletelim CPU kullanimi max olacaktir. Bunda application.processmessages in etkisi yok.
Asagidaki kodun icindeki for dongusu fonksiyonun uzun zaman calismasini simule etmek icin eklendi. Kodlamayi state machine mantigi ile yazdim ve sorunsuz kullaniyorum.
Thread konusu da bu tartismadan sonra bir acik kapi ve gerektiginde kullanirim artik.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Calistir: TButton;
BEKLE: TButton;
procedure CalistirClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure BEKLEClick(Sender: TObject);
private
{ Private declarations }
ShowKey : Boolean;
public
{ Public declarations }
end;
var
Form1: TForm1;
basladi,bekle_:boolean;
i:integer;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
bekle_:=false;
basladi:=false;
end;
procedure TForm1.CalistirClick(Sender: TObject);
var i:integer;
begin
if (basladi or bekle_) then exit;
Basladi:=true;
for i:=0 to 10000 do
begin
form1.caption:=inttostr(i);
refresh;
repeat
Application.ProcessMessages;
until not bekle_
end;
Basladi:=false;
end;
procedure TForm1.BEKLEClick(Sender: TObject);
begin
If not basladi then Bekle_:=true;
Bekle_:=Not Bekle_;
If bekle_ then Bekle.Caption:='Devam Et'
else Bekle.Caption:='Bekle'
end;
end.
Alıntı yapılan: "controller"@bunalmis
yukarıdaki gibi bir programı başlattığınızda çalışan ilk ve tek thread "ui (user interface) thread" dir. bu thread kullanıcı ile sizin programınız arasındaki iletişimi sağlayan uygulama pencerenizi yönetir. eğer siz uzun sürecek işlemi oluşan bu ilk ui thread içine yazarsanız yaptığınız işlem süresince uygulama pencereniz kullanıcıya cevap veremeyecektir. siz bunu engellemek için application.processmessages gibi bir çözüme başvurmuşsunuz. ancak burada doğru olan uzun sürecek işlemlerin, işlem çok basit dahi olsa ui thread den bağımsız olarak ayrı bir thread de yapılmasıdır. konu başlığında bahsettiğiniz "işi bilenler" bu şekilde yapmaktadırlar.
Bu tartismadan sunu anladim eger dogruysa sizlere hak veriyorum.
Eger telefon caldiginda programi beklemeye alirsam program hala cpu dan buyuk ilgi talep ediyor. Halbuki beklemeye alindiginda internette gezinmek isteyebilirim.
Benim uyguladigim mantikta internet gezintim yavaslayacak.
Thread kullanirsam ve programi beklemeye alirsam internette hizli gezinecegim.
Dogrumu?
Evet / Hayir?
bu konuyu uzunca açıklamaya şu an vaktim yo ancak sizin burada yaptığınız işletim sisteminin akışına boş yere karışmak oluyor. ben işletim sisteminin yerinde olsam beklemedeki application.processmessages işlemi için "kardeşim zaten hiç bir iş yapmadan bekliyorsun, ne diye benim işime karışıyorsun" derdim. sizin yaptığınız kulağı tersten tutmak gibi.
en klas programı da yapsan, donan bir program kötüdür. mesela windowsun ses kaydedicisi var. bu ufak program mis gibi . hiç donmuyor. bir yandan ses çalıyor veya kaydediyor. müsait zamanda ekrana ufak grafik gibi birşey çiziyor. ara sıra sıkışıp donduğunu hiç görmedim. Pencereyi sürüklerken sadece görsel kısım kesintiye uğruyor. Bunun sebebi, sesle ilgili işlemlerin, ses kartından gelen bilgilerin arka planda başka threadler tarafından yürütülmesidir.
(http://i45.tinypic.com/157hlxj.jpg)
@bunalmıs hocam
Bilgisayarda bsizin programınızdan başka bir program çalışmayacaksa , ve gerçekten hız ihtiyacınız varsa. bence sizin yönteminiz en doğru yöntem.
Ama bilgisayarda başka programların da çalışma ihtimali varsa ,
Örneğin makina parçayı işlerken , aynı makinada başka bir parçanın çizimi yapılacaksa veya başka bir iş yapılacaksa kesinlikle yanlış yoldasınız.
Programı cihazla birlikte satacaksnız sanıyorum. Eğer alıcı ben olsam makina işini yaparken başka işlerle uğraşabilmek isterim. Sadece beklemeye aldığımda değil her zaman internette hızlı gezinebilmek isterim. Ama derseniz ki: Bu isteğiniz zaten bu işin mantığına aykırı , makina parçayı işlerken başkaiş yapılmaz , yapılmaması gerekir. O zaman size hak veririm
Çünkü:
Windows mesaj tabanlı bir işletim sistemi. Ve bazı mesajlar üzerine yazılır tip mesajlar.
Örneğin Timer mesajları. Bir timer mesajı işlenmeden başka bir timer mesajı gelirse , bu mesaj öncekinin üzerine yazılır. Yani biz bir zaman geçmiş olduğunu biliriz ama ne kadar zama geçmiş olduğunu asla bilemeyiz.
@ thread olmalı diyen diğer arkadaşlar.
While döngüsü içerisinde application.processmessage kullanmanın, kendi programımız açısından hiçbir sakıncası yok. Ayrıca iş yükünü de artırmaz. Thread kullanırken yapılan şey de zamanı tüm thread'lere paylaştırmak ve tüm kanalların mesajlarının işlenmesine olanak sağlamaktır.
Ayrıca Thread hiçbir zaman while döngüsünden daha hızlı olamaz. While içerisinde processmessage dahi kullansanız thread'den daha yavaş değildir.
Bunalmış hocamın kullandığı yöntem mesaj işleme sürelerini sizin insafınıza bıraktığı için çok doğru bir yöntem değil. OOP programlama felsefesine de biraz aykırı. ama Tüm CPU benim programımı yürütecekse , yürütecek başka bir program yoksa , ve OOP programlama felsefesi de çok umurumda değilse , neden bu yöntemi kullanmayayım??????
Thread kullanıp kullanmamak asıl programcıya kalsın, o yüzden de sadece kodun çalışmasını değiştirmeden daha farklı biçimde yazıp bıraktım.
Fakat şöyle bir durum daha var;
Alıntı YapWhere ProcessMessages is called, be aware that all events will be processed, even events that you may not want to have processed. It's up to you to protect your application from the user. Run the application again. Click the button. Wait a few seconds. Click the button again. Notice what has happened. The function started over again.
http://delphi.about.com/od/objectpascalide/a/delphi-processmessages-dark-side.htm
Ayrıca ne kadar çok kanal (thread) açarsanız, performansınız da okadar düşer.
Alıntı yapılan: "bunalmis"
Application.processmessages neden CPU yukunu artiriyor anlamadim.
Bu komut sayesinde procesure yada fonksiyon icine girildiginde disarida olup biten olaylarin da ara ara cevaplanmasi icin imkan taniyoruz.
eğer yapacağınız işlemi ayrı bir thread içerisinde çalıştırırsanız bu bahsettiklerinizi "ui thread" zaten yapıyor. sizin bunu düşümenize gerek yok. siz ui thread içine yazdığınız kod ile ui thread in kendi yapacağı işi aksatıyorsunuz.
Alıntı yapılan: "bunalmis"
Anladigim kadariyla PC de yazacagim program tek bir isle değil de bir kac isle ugrasacak olsaydi ve basla dedigimde uc isi de ayni zamanda baslatsaydi o zaman bu dediginiz yontem isime yarardi.
buradaki yapılacak iş sayısı hesabınız eksik. ui (user interface) zaten başlıbaşına biş iştir, ve bu işi ui thread yürütür. siz bu işlemden bağımsız her işi ayrık olarak düşünmelisiniz. yani işlem sayısı = (ayrık yapılacak iş sayısı + 1 ). buradaki +1 ui yi temsil eder. bu hesaba göre sizin programınız toplamda 2 iş yapmaktadır. buda sağlıklı bir çalışma için ikinci bir thread gerektirir.
Alıntı yapılan: "Klein"
@ thread olmalı diyen diğer arkadaşlar.
While döngüsü içerisinde application.processmessage kullanmanın, kendi programımız açısından hiçbir sakıncası yok. Ayrıca iş yükünü de artırmaz. Thread kullanırken yapılan şey de zamanı tüm thread'lere paylaştırmak ve tüm kanalların mesajlarının işlenmesine olanak sağlamaktır.
Ayrıca Thread hiçbir zaman while döngüsünden daha hızlı olamaz. While içerisinde processmessage dahi kullansanız thread'den daha yavaş değildir.
Bunalmış hocamın kullandığı yöntem mesaj işleme sürelerini sizin insafınıza bıraktığı için çok doğru bir yöntem değil. OOP programlama felsefesine de biraz aykırı. ama Tüm CPU benim programımı yürütecekse , yürütecek başka bir program yoksa , ve OOP programlama felsefesi de çok umurumda değilse , neden bu yöntemi kullanmayayım??????
Modern işletim sistemleri "preemptive multitasking" ile çalışır. yani hangi kodun ne kadar süre çalışacağına öncelik seviyesine göre işletim sistemi karar verir. siz preemptive çalışan bir koda "application.processmessage" ekleyerek işletim sistemine "ben işlemlerimi tamamladım, birazda diğer işlere bak, sonra yine benim işime dönersin" diyerek işletim sisteminin kendi akışına müdahale ediyorsunuz. buda sizi günümüzden 20 yıl öncesine windows 3.1 in yaptığı gibi "cooperative multitasking" çalışan bir yapıya götürüyor ki günümüzde mikrodenetleyicilerde çalışan rtos lar bile preemptive multitasking yapmaktadır. yani işlemleri ayrı thread lerde çalıştırırsanız, sizin manuel kod ile yaptığınız bu işlemleri işletim sistemi zaten kendisi halletmektedir.
aslında burada @bunalmis ın yaşadığı sorunlar, üzerinde işletim sistemi çalışan bir cihaza program yazarken hala salt kod çalıştıran mikrodenetleyicilerde olduğu gibi;
main()
{
while(1)
{
}
}
mantığından kurtulamamış olmasından kaynaklanmaktadır.
Controller ne demek istedigini artik daha iyi anliyorum. Thread konusunu da gayet iyi kavradim. 5 Saat surecegini soyledigim fonksiyonu da bir kac thread e bolup windowsa cok zaman kazandirabilir ve programimla birlikte bir kac programin da calismasini saglayabilirim.
Ancak bu su anki uygulamamdaki yazilimimi baltalamak olur. Sebebi gayet acik.
Threadler arasindaki senkronizasyonu da saglamak icin ilave bir cok kod koyacagim ve threadlerin calismasi icin windowsun bana ayirdigi zamani beklemek durumunda kalacagim.
Sonuc olarak prostatdli birinin isemesi gibi threadler kesik kesik calisacak. Bunu bufferli donanimla asabilirim. Neyseki zaten donanimim buffer iceriyor. Ancak bu asamada yazilimin mantigini thread calismasina kaydirmak projejimin cikis tarihini cok geriye atacak.
Klein in de dedigi gibi yazilimim calistigi anda artik patron benim diger yazilimlar basinin caresine baksin. Bir bakima buna da mecburum cunku normalde bir PC sirf bu tip yazilimlara heba ediliyor. Ornegin HP, scoplarinin icine artik PC ana karti koyuyor. Bu kartta eskiden W98 vardi simdilerde muhtemelen XP vardir. Sanirim hic kimse HP ye thread kullan yada kullanma diyemez cunku PC de kosan tek yazilim scop yazilimi.
Aslinda konunun buralara gelmesine ve thread konusunun tartisilmasina sevindim.
Basliktaki cumleyi kurmamin sebebi goto komutlari kullanarak yazdigim ve ornegini vedigim kisa kod parcasinin isi bilenlerce nasil yazilacagiydi fakat konu yanlis anlasildi ve olay thread kullanimina kaydi. Iyiki de yanlis anlasildi.....
Lazım olanlar varsa eğer, yeri gelmişken belirtmek istedim..
.Net'te bu thread olayı "BackroungWorker" ile söylediğiniz uzun işlemler ara kodlar olmaksızın yapılabiliyor.
Alıntı yapılan: "bunalmis"Sanirim hic kimse HP ye thread kullan yada kullanma diyemez cunku PC de kosan tek yazilim scop yazilimi.
Hele scop yazilimini dediğiniz gibi yapayim derseniz kesin sorun çıkar. Donanımla haberleşme işi için mutlaka en az 1 adet ayri thread gerekir. yoksa sahadan geri dönecektir. Ancak müşteriyi tembihlediysen, bu programın penceresini asla basılı tutmamalısın, öyle elini kaldırmadan kıllık olsun diye pencereyi sakın basılı tutup gezdirme ! dediysen sorun olmaz. thread, işi kesintiye uğratmak için değil, bilakis kesintiyi önlemek için kullanılır. her application.process mesages dediğin yer bir kesintidir.
bu yazılımın hiç bir görsel tarafı yoksa sadece çalışmakla meşgul ve gelen bilgileri uygun gördüğü zaman bir yere yazıyorsa ve başka da hiç bir programla haberleşmiyorsa ayrı thread kullanmasan da olur.
fakat yapılacak iş için belki güzel bir komponentl kullanılabilir. Bazıl komponent kendisi ayrı thread başlatır.
Örneğin bilgisayarda arama yapmak için bir komponent kullandım. arama esnasında ayrı bir thread başlıyor. son sürat arıyor. normalde programın donması gerek
Artik konu kapanmistir. Thread konusunu baska bir baslikta tartisabiliriz.
Dedim ya patron benim. Yazilimimi kullanacaklar programin 2. veriyonu cikincaya kadar V01 ile idare edecekler.
Programin pause butonu var. Programa bir de burun karistirma ozelligi ekledim.
Diyelimki burnunuzu karistiracaksiniz ve bu esnada makinanin da beklemesini istiyorsunuz bu durumda mouse ile form penceresi uzerine geliyor ve basili tutuyorsunuz.
Gordugun gibi care tukenmiyor.
Alıntı yapılan: controller - 13 Ocak 2010, 00:37:39
............
aslında burada @bunalmis ın yaşadığı sorunlar, üzerinde işletim sistemi çalışan bir cihaza program yazarken hala salt kod çalıştıran mikrodenetleyicilerde olduğu gibi;
main()
{
while(1)
{
}
}
mantığından kurtulamamış olmasından kaynaklanmaktadır.
Bu mantığın nasıl dışına çıkacağım çözemedim.
Bir butona basıldığında seri porttan Esc karakteri gönderip, seri porttan cevap gelmesini bekleyen ve gelen cevabı form captiona yazan minik bir windows yazılımını yukarıdaki mantıktan farklı şekilde nasıl yazarız?
Bu soruyu özellikle Controller'a soruyorum.
Alıntı yapılan: peko - 13 Ocak 2010, 14:35:13
Lazım olanlar varsa eğer, yeri gelmişken belirtmek istedim..
.Net'te bu thread olayı "BackroungWorker" ile söylediğiniz uzun işlemler ara kodlar olmaksızın yapılabiliyor.
Doğru. Bu tür bir yapı uzun süren işlemleri için şart, yoksa GUI'nin kilitlenmesine neden olabiliyor. Daha teknik konuşmak gerekirse, uzun süren iş GUI thread'i altında çalıştırılırsa, event listener'lar yatıyor, söz konusu uzun iş bitene kadar da GUI kilitlenmiş oluyor, yani event listener'lara sıra gelmiyor. Java'da da durum benzer. Delphi hiç bilmediğim için yorum yapamam ama mantığının çok farklı olduğunu sanmıyorum.
bunalmis hocam, öyle sanıyorum ki bir çeşit event listener'a ihtiyacın var. C#'ta aynı buton vs. gibi GUI elemanlarına event listener bağlandığı gibi seri port nesnesine de bir event listener (SerialPort.DataReceived) bağlanır. Arka planda nasıl çalıştığından emin değilim ama sanırım PIC'teki kesme mantığına benzer şekilde çalışıyor. Delphi'de böyle bir yapı var mıdır bilmiyorum ama bu tarzda bir yapı kullanılmazsa sonsuz döngüyü ayrı bir thread'de çalıştırmak bile performansı düşürecektir.
Seri iletişim için ayrı therad oluşturdum. Adama al bunu yolla ve geleni bekle ve alınca da bana ver şeklinde programımı yazdım.
Ama bu kezde formdaki procedure threadin cevap vermesini bekliyor.
Yani controllerın bahsettiği while döngüsünden kurtulamıyorum.
İnternette biraz araştırayım dedim. Sanırım yukarıda anlattığıma benzer bir yapı Delphi'de de var. Ancak burada (http://sourceforge.net/projects/comport/) bulunan 3. parti bir kütüphane yüklemek gerekiyor. Burada (http://objectmix.com/delphi/402271-how-create-serial-port-events.html) bir örnek verilmiş.ComPort1.OnRxChar := CommPort1RxChar;
Bu satır ile seri port nesnesine bir listener bağlanmış gibi görünüyor.
Burada seri portu örnek olması için verdim. Asıl amaç verdiğim örnekteki gibi bekleme durumlarına karşı uygulanacak yöntemlerin neler olacağı.
Yukarıda bahsettiğim gibi, nesne tabanlı dillerde bildiğim kadarıyla sorun event listener'lar ile çözülüyor. Diğer taraftan, thread'lerin uykuya alınması ve sinyalle uyandırılması da söz konusu olabilir. Gerçi ilk durumun arkasında yatan mantık da bu sanırım.
Bir de mutex olayı var ki sanırım thread kütüphaneleri mutex'te sıra bekleyen thread'leri de uykuya alıyor. mutex boşa düşünce de sıradan uyandırıp işleme sokuyor. Gerçi bu durum konumuzla çok ilgili değil, çünkü kütüphanenin kendi içinde yaptığı bir işlem. mutex kuyruğunda sonsuz döngü olmaması açısından bu durum bir örnek niteliğinde.
@bunalmis
Öncelikle delphi kullanmadığım için örnek kod veremiyorum.
Seriport için kullandığınız komponentin "DataReceived" gibi bir Event'ı varsa, seri porttann veri geldiğinde yapacağınız işlemleri buraya yazabilirsiniz. Ana döngüde verinin gelmesini beklemenize gerek kalmaz.
Eğer kullandığınız komponentin yukarıda anlattığım gibi veri geldiğinde tetiklenen bir Event'ı yoksa, seri port işlemler için oluşturduğunuz thread içinde veri gelmesini beklersiniz. Bu ana döngünüzün akışına engel olmaz. Veri geldiğinde ise "callback" denilen yöntem ile pointer fonksiyon olarak tanımlayacağınız bir fonlsiyonu çağırarak gerekli işlemleri yapabilirsiniz.
Sorunuzu yanlış anlamadıysam böyle bir çözüm olabilir. "delphi callback function" yazarak arama yapabilirsiniz.
Bu kodu ne için kullanmak istiyorsunuz ya da amacınız nedir? ona göre birşeyler düşünülebilir. Yıllardır Delphi kullanırım ama Profesyonel programcıların pek label kullandığını görmedim.
.net Backgroundworker
http://ferruh.mavituna.com/backgroundworker-ile-calismak-oku/ (http://ferruh.mavituna.com/backgroundworker-ile-calismak-oku/)
Delphi ile Thread Kullanımı Basit Bir Anlatım
http://www.diyezon.com/2007/10/02/delphi-ile-threadkanal-kullanimi-bolum-1/ (http://www.diyezon.com/2007/10/02/delphi-ile-threadkanal-kullanimi-bolum-1/)
Delphi callback function için örnek programınız varmı?
http://tinyurl.com/y3w3od3
Yaptın bir iyilik, oradaki linklerden basit anlaşılır bir callback örneğini cuttcopy yapabilirmisin? Ben bulamamıştım.
http://www.delphi-central.com/callback.aspx
http://delphi.about.com/od/windowsshellapi/a/callback_delphi.htm
Bunları bir incele istersen
delphi basic ve delphi about sitelerinde çoğu şeyin temelini bulabilirsin ayrıca delphi dökümanlarına da bakmanı tavsiye ederim bir sürü pdf dosyası var delphiye ait. eğer bulamazsan haber ver evdeki pc de hepsi var gönderirim sana
Callback fonksiyon ne ise yariyor kisaca anlatacak varmi?
http://www.codeguru.com/cpp/cpp/cpp_mfc/callbacks/article.php/c10557
Alıntı yapılan: controller - 13 Ocak 2010, 00:37:39
Aslında burada @bunalmis ın yaşadığı sorunlar, üzerinde işletim sistemi çalışan bir cihaza program
yazarken hala salt kod çalıştıran mikrodenetleyicilerde olduğu gibi;
main()
{
while(1)
{
}
}
mantığından kurtulamamış olmasından kaynaklanmaktadır.
Bu mesaj windows icin yazdigim programlarda bana mirengi noktasi oldu.
Ancak hala sikintilarim var.
Windows isletim sisteminde kullanilmak uzere tasarlayacagimiz elektronik devrelerin windows mantigina uygun kullanilabilmesi icin
elektronik cihazlarimizin sorgulandiginda cevap veren tipte degil de, gerekli durumlarda windowsa sikayet yapan daha dogrusu
ispiyonculuk yapan tipte tasarlanmasi gerektigi sonucuna vardim.
Neden derseniz.
Sorgu mantigiyla PC ye bilgi gonderen cihazlar varsa, windows tarafinda ozellikle kritik durumlardan derhal haberdar olmak icin
cihazi cok sik sorgulmak gerekiyor.
Bu da dongu tipi yapilar kurmamizi gerektiriyor.
Halbuki ispiyon yapan turde cihaz tasarlarak windows tarafinda dongu mantigindan kurtulacak ve event mantigiyla kod yazabilecegiz.
Bu konularin uzmanlari ne dusunuyor?
karşılıklı veri alışverişinde mesela ftp tarzı bir program yazdığınızda belli sürelerle veriyi yakalayan alıcılar olur bu şekilde döngü kurmaya gerek kalmaz. o kendi işini asekronize olarak ayrı bir işlemde ana işlemleri etkilemeden çalışır. gördüğüm kadarıyla PIC programcıları masaüstü programlarında aynı mantıkla işlem yapmaya çalışıyorlar ki çok yanlış. Ben mesela sonsüz döngüyü ilk defa PIC de gördüm hiçbir zaman da kullanmadık o tarz işleri. bir tane servis yada işleç olur belirli zaman aralığında işlem yapar ve ona göre de gerekli prosedürleri çalıştırır. Delphi için bu tarz işlemler genelde timer componenti ile veya yeterli gelmiyorsa ayrı bir thread yapılarak basitçe özülür. Biz daha çok olay bazlı programlama kullanıyoruz. Aşağıdaki linkten programlama çeşitlerini de görebilirsiniz;
http://en.wikipedia.org/wiki/Comparison_of_programming_paradigms
Bugune kadar devrelerimi (islemci yazilimlarini) PC sorguladiginda sonuc gondercek mantigi ile tasarliyordum.
FT232 yi ureten firmanin hazir verdigi D2XX.DLL bildigim kadariyla event mantigi ile calismiyor.
Eger sorgulama mantigi ile calisiyorsa bir an once D2XX.DLL den kurtulmam gerekecek.
D2XX.DLL kullanarak USB den veri geldiginde event uretecek sekilde program yazabiliyormusunuz?
Su ana kadar ben hep data gelmismi diye sorgulama durumunda kaldim.
http://www.efg2.com/Lab/Library/Delphi/IO/PortIO.htm
http://www.lvr.com/hidpage.htm
http://www.delphi-jedi.org/
burada çok güzel delphi usb componentleri var bir incele istersen
Thread içinde sanki ikinci bir işlemcim varmış gibi program yazdım. Bu işlemci kapalı döngü içinde sürekli dönüyor ve usb porta bağlı harici donanımımı sorguluyor delphi ana programının usb cihazla ilişkisine de aracılık ediyor.
Ana program cihazdan veri okumak istediğinde yada cihaza veri yollamak istediğinde derdini threde anlatıyor.
Thread yazılım cihazdan okuduğu verileri delphi ana yazılımına SendMessage ile yolluyor. Ancak ana yazılım bu mesajların bazılarından haberdar olamıyor. Ana program threde derdini SendThreadMesage ile yolluyor ve burda hiç kayıp olmuyor.
Böyle bir problem yaşadınızmı? Bu yönteme alternatif öneriniz varmı?
Ben thread için genelde jedinin thread componentini kullandım çok fazla thread işim olmadığından dolayı. Timer yapısında çalışıyor ama her iş için bir thread açıyor tüm işi de kendi üstleniyor.
http://www.delphi-jedi.org/
Jedinin thread componenti için neyi indirmem lazım? Ana sayfaları bayağı kalabalık.
http://jvcl.delphi-jedi.org/