Getmessage ve Thread Hakkında (Uzman Sorusu) [ÇÖZÜLDÜ]

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
G.Arkas
Üye
Mesajlar: 829
Kayıt: 01 Eki 2007 07:16
Konum: İstanbul
İletişim:

Getmessage ve Thread Hakkında (Uzman Sorusu) [ÇÖZÜLDÜ]

Mesaj gönderen G.Arkas »

Merhaba arkadaşlar;

Üzerinde çalıştığım bir projede formsuz ve arka planda çalışan bir uygulamam var. Bazı şeyleri kontrol ediyor.

Uygulamamın ana Type'ı

Kod: Tümünü seç

 
type
TListeningSvc = class(TThread)
Ana mimari Thread üzerine kurulu. Buna bağlı olarak farklı bir Unit'te

Kod: Tümünü seç

type
  TScanner = class
yapısında bir sınıfım var. Bu sınıfı belirli şartlar oluştuğun da ayağa kaldırıyorum. Yalnız ana mimari Thread olduğu için Scanner sınıfı ayağa kalktığında tutunacak bir dal bulamadığı için asılı kalıyor ve işlem yapmıyor. Bende bu sorunu sınıfımın içerisinde tetikleme amacıyla kullandığım bir procedure'nin son satırına;

Kod: Tümünü seç

 while GetMessage(Msg, 0, 0, 0) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
koyarak çalışmasını sağlıyorum. Bu aşamada problemsiz bir şekilde çalışmaya başlayan sınıfım bu dakika itibari ile hiçbir zaman sonlanamıyor. Bir şekilde yukarıda ki satırı kırmam lazım ama hiçbir şekilde kıramadım.

Denediğim yöntemler.

- Scanner sınıfını Thread olarak oluşturma
- While GetMessage apisini Thread içerisine alma
- PostMessageQuit kullanma
- PostMessage(Fhwnd, WM_TerminateYourself, 0, 0) kullanma.
- Ana Unite içerisinde Handle ile procedure sonlandırma (AllocateHwnd - DeallocateHwnd)

Bunların dışında öneri de bulunabilecek arkadaşlarım varsa çok memnun olurum.

Anlaşılmayan bir yer varsa soru sorabilirsiniz.

İyi çalışmalar....
En son G.Arkas tarafından 10 Eyl 2014 05:56 tarihinde düzenlendi, toplamda 1 kere düzenlendi.
Resim
Kullanıcı avatarı
Battosai
Üye
Mesajlar: 1316
Kayıt: 01 Eki 2007 12:02
Konum: Ankara

Re: Getmessage ve Thread Hakkında (Uzman Sorusu)

Mesaj gönderen Battosai »

Yazdıklarınızdan ne yapmak istediğiniz pek anlaşılmıyor. Anladığım kadarı ile Thread içinden dıştaki bir nesneye erişmeye çalışıyorunuz ya da tam tersi bir durum var. Böyle bir durumda hata almanız normaldir. Thread uygulamalarında temel prensip Thread'in tamamen bağımsız çalışmasıdır. Yani thread ne iş yapıyorsa işi yapan sınıf,fonksiyon,procedure thread içinde tanımlanmalı ve koşturulmalıdır. Yapılacak işe göre oldukça karışık bir hal alabilir uygulamanız.

Thread mevzusunda detaylı bilgi için burayı inceleyin
http://www.tugrulhelvaci.com/?p=443
Kullanıcı avatarı
G.Arkas
Üye
Mesajlar: 829
Kayıt: 01 Eki 2007 07:16
Konum: İstanbul
İletişim:

Re: Getmessage ve Thread Hakkında (Uzman Sorusu)

Mesaj gönderen G.Arkas »

@Battosai

İlgilendiğin ve cevabın için çok teşekkür ederim. Thread dışından erişmeye çalıştığım çok basit bir sınıf. Bu sınıfta Stream ve Buffer üzerinden iletilen veriler var. Bu veriler bir socket vasıtasıyla gidip geliyor. Ana thread içerisinde tanımlamayı denedim ama sonuç aynı. Bu arada uygulama üzerinde hiçbir hata almıyorum. Debug yaptığımda Thread çalışmaya başlıyor ama "diğer sınıfıma bağlı Stream çalışmıyor".

Şöyle belirteyim açıklamaya çalışmak adına;

Kod: Tümünü seç

procedure ReceiveData(Text: String; Socket: TClientSocket);
begin
burada socket receive buf ile Text değişkenini parselliyorum ve Stream döndürüyorum (Yolluyorum)
end//
Bu procedure'ün altına yukarıda ki satırı eklemezsem procedure işlemiyor. Ya Delay koymam lazım (Belirttiğim süre içerisinde çalışıyor süre bitince duruyor) ya da ShowMessage koymam lazım.(Mesaj kapatılıncaya kadar çalışıyor kapatınca duruyor)
Bu zaten başlı başına bir olay. Bunu yukarıda ki şekilde çözdüm. Ama bu seferde Streamı (Procedure ReceiveData) sonlandıramıyorum doğal olarak. Sıkıntı burada başlıyor. O satırda ki kilidi bir şekilde kaldırmam lazım. Thread dışında oluşturduğum basit bir sınıf bu. Hiçbir ayrıcalığı yok. Ama bir akış olduğu için (Stream) sanırım tutunamıyor. Uygulamayı form ile yapsam sorun kalmaz ama o da uygulamanın zararına olur. Çünkü Lisans vs kontrolleri yapan bir servis gibi çalışıyor. (Servis değil ama)

Açıksası sorunu tam olarak bende anlayamadığım için anlatmakta zorlanıyor olabilirim çünkü gerçekten uzun zamandır Thread işlemleriyle çalışırım ilk defa böyle bir sorun ile karşılaştım.
Resim
omurolmez
Üye
Mesajlar: 187
Kayıt: 31 Eki 2012 11:41

Re: Getmessage ve Thread Hakkında (Uzman Sorusu)

Mesaj gönderen omurolmez »

... ama diğer sınıfıma bağlı stream çalışmıyor.
Stream çalışmıyor ne demek ?
Stream den okuma yaparsınız kullandığınız işleve / sınıfa göre, ya timeout boyunca askıda kalır ya da tamponda olan kadar veri ile geri döner. İki durum da yasaldır. Madem ki thread içinde çalışıyorsunuz, thread iniz bir stream (sonunda bir i/o winapi) nedeniyle veri gelinceye kadar askıda kalabilir. Bu gayet doğal hatta yararlı birşeydir. Windows, belirli i/o hareketlerinin sonuçlanmasını bekleyen thread leri tamamen durdurur ancak i/o sonuçlanınca tekrar (hemen) başlatır.

Eğer thread inizin durmaması gerektiğini düşünüyorsanız,
a. Belki de işi birden fazla thread e bölmeye ihtiyacınız vardır
b. timeout lu beklemeler yapabilirsiniz (WaitForMultipleObjects işlevinin INFINITE den küçük değer ile çağrılması)
c. Hem zorluğu göze alır hem de sadece winapi platformunda kalırsanız, overlapped i/o, queued file operation vb. metodlara bakabilirsiniz.

Yaptığınız işlem (message loop) sizin de bildiğiniz gibi main vcl thread içinde zaten yapılıyor. Farklı bir thread içinden çağırmak senkronizasyon problemlerine yol açabilir mi (bu şahsi fikrim, emin değilim) ? stackoverflow da başka dillerde bile mesaj döngüsünün başka thread içinde tekrarlanmasının doğru olmayacağına dair tartışmalar var.

Not: Sınıf adında service kelimesi geçiyor. Eğer service application yazmaya çalışıyorsanız ve delphi vcl kullanmadan yapmaya çalışıyorsanız, o zaman message loop u kurmanız tabii ki şart. Eğer öyleyse, sorunuzda belirmelisiniz.
Ömür Ölmez
Kullanıcı avatarı
G.Arkas
Üye
Mesajlar: 829
Kayıt: 01 Eki 2007 07:16
Konum: İstanbul
İletişim:

Re: Getmessage ve Thread Hakkında (Uzman Sorusu)

Mesaj gönderen G.Arkas »

@Ömürölmez

Merhaba Hocam;

Stream çalışmıyor derken Stream'ı koşturduğum procedure çalışmıyor demek istemiştim yukarı da belirtmiştim zaten.
Stream den okuma yaparsınız kullandığınız işleve / sınıfa göre, ya timeout boyunca askıda kalır ya da tamponda olan kadar veri ile geri döner. İki durum da yasaldır. Madem ki thread içinde çalışıyorsunuz, thread iniz bir stream nedeniyle (sonunda bir i/o winapi) nedeniyle veri gelinceye kadar askıda kalabilir. Bu gayet doğal hatta yararlı birşeydir. Windows, belirli i/o hareketlerinin sonuçlanmasını bekleyen thread leri tamamen durdurur ancak i/o sonuçlanınca tekrar (hemen) başlatır.
demişsiniz. Evet ama burada farklı bir durum var kaçırdığınız. Ben Stream çalıştırdığım procedure'e ShowMessage yada Delay eklediğim de hiçbir sorun olmadan o procedure tetikleniyor. Windows bunu neden bir mesaj öğesine ya da gecikmeye bağlasın?
Windows, belirli i/o hareketlerinin sonuçlanmasını bekleyen thread leri tamamen durdurur ancak i/o sonuçlanınca tekrar (hemen) başlatır.
Evet doğru ama burada sadece Thread başlıyor ve tetiklemesi gereken işlemleri başlatamıyor. Dolayısıyla Input/Output işlemi olmadığından Thread durmuyor ve yeniden başlamıyor. Thread açık bir şekilde kalıyor.

Burada ki problem sanki daha farklı gibi. Create edilen sınıf ayakta duramıadığı için üzerine tanımlı procedure ler çalışamıyor. Ama neden sorunum bu zaten?

MessageLoop kullanmamın sebebi de bu zaten. MessageLoop'da Thread dışında oluşturduğum için kapatamıyorum.

Not : SvcApp değil.
Resim
Kullanıcı avatarı
G.Arkas
Üye
Mesajlar: 829
Kayıt: 01 Eki 2007 07:16
Konum: İstanbul
İletişim:

Re: Getmessage ve Thread Hakkında (Uzman Sorusu) [ÇÖZÜLDÜ]

Mesaj gönderen G.Arkas »

Sorunu çözdüm arkadaşlar. Ana thread'i hiç karıştırmadan cevapların geldiği procedure'ü thread içerisine aldım ve GetMessage komutunu thread'in dışarısında bıraktım. Böylece hem uygulamam askıda kalmadı hemde stream'in çalıştığı procedure görevini rahatlıkla yerine getirdi.

Cevap gönderen herkese çok teşekkürler.
Resim
Cevapla