Isi bilenler bu kodu nasil yazardi?

Başlatan bunalmis, 11 Ocak 2010, 19:35:25

Klein

@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??????

SpeedyX

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.

controller

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.
Hesabım OG tarafından haksız bir şekilde pasif yapılmıştır.

z

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.....
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

peko

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.
" Bazıları zeka'sını iş'i zorlaştırmak için, bazıları ise kolaylaştırmak için kullanır.. "

wsxwsx

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

z

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.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

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.

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Tagli

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.
Gökçe Tağlıoğlu

z

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.



Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Tagli

İnternette biraz araştırayım dedim. Sanırım yukarıda anlattığıma benzer bir yapı Delphi'de de var. Ancak burada bulunan 3. parti bir kütüphane yüklemek gerekiyor. Burada bir örnek verilmiş.
ComPort1.OnRxChar := CommPort1RxChar;
Bu satır ile seri port nesnesine bir listener bağlanmış gibi görünüyor.
Gökçe Tağlıoğlu

z

Burada seri portu örnek olması için verdim. Asıl amaç verdiğim örnekteki gibi bekleme durumlarına karşı uygulanacak yöntemlerin neler olacağı.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Tagli

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.
Gökçe Tağlıoğlu

controller

@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.
Hesabım OG tarafından haksız bir şekilde pasif yapılmıştır.

orhanc

#29
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/

Delphi ile Thread Kullanımı Basit Bir Anlatım
http://www.diyezon.com/2007/10/02/delphi-ile-threadkanal-kullanimi-bolum-1/
i'm doing nothing... Giddy Up  http://www.drorhan.com