Yorumları: 12
Konuları: 3
Kayıt Tarihi: 19-03-2021
Aktif Kullandığınız Delphi Sürümü:
- Delphi 10.3
- Delphi XE Serisi
Rep Puanı: 149 Başlangıç
(21-03-2021, Saat: 22:21)mrmarman Adlı Kullanıcıdan Alıntı: 0 olması doğal TickCount milisaniye cinsinden, onun altınaki her şey 0 gelir.
Önerime geleyim. Size iki seçenek sunuluyor.
1. Optimizasyon ile işlem süresini azaltmak. Öncelik projenizin mainthread dahilinde sadece ve sadece noktaları collect etmek. Çizim işlemini bağımsız bir thread'e koyup, hali hazıda sırada bekleyen noktaları demlenerek diye tabir edeyim -tabiri bağışlayın- ekranda görüntülenmesini izlemek. Taa ki veri akışı sona erip de liste sonuna ulaşana kadar listeye syncronize sürecek bir thread.
2. Her gelen veri için bağımsız birer TThread açıp TObjectList altına ekleyip, FreeOnTerminate ile işi biten Thread'in kendini yok ederken EVENT altında TObjectlist altındaki Thread'i DELETE etmek. Bu işlem için öngördüğüm aynı anda çalışacak en fazla 13 thread açıp kapatacaktır diye değerlendiriyorum.
Hocam Teşekkür ederim önerilerinizi uygulayacağım, sonucu buraya yazacağım.
Yorumları: 902
Konuları: 68
Kayıt Tarihi: 30-06-2017
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 8.392 Üstad
Sürekli thread oluşturup yok etmeyi önermiyorum.
Bir Thread başlatmak, yeni bir process oluşturmaktan çok daha hızlı olsa da, yine de nispeten yavaş bir işlemdir. Yeni bir Thread oluşturmak kolayca birkaç milisaniye sürebilir. Yüksek performanslı uygulamalarda her milisaniye önemli olduğundan, Task ve Pattern odaklı kitaplıkların çoğu ( mesela PPL gibi ) bir Thread Pool (Kanal havuzu) kavramını kullanır. Bu sizinki gibi projelerde performansa önemli katkılarda bulunur.
O nedenle sürekli thread oluşturmaktansa Thread Pool kavramını araştırarak işe başlayabilirsiniz. Bu sayede işi biten threadler bellekten atılmayıp hazırda bekler. İş geldiğinde hemen işe koyulur. Bu da performans olarak uygulamaya yansır.
Fakat ben tüm bunlarla ilk başta uğraşmaktansa daha basit bir yaklaşım öneriyorum. En azından deneyin;
1) 2 ayrı threadınız olsun,
2) Birincisi sürekli veri okuyup ortak erişilen bir tampona okuduğunu yazsın.
3) İkinci threadiniz ise tampondan sırası gelen verinin ekranda gösterilecek olan koordinat hesaplamalarını yapsın.
4) Hesaplama bitip çizim anına geldiğinizde ana threade çizim için ana threade syncronize çağrısı yapsın. ( Belki Queue de kullanabilirsiniz, duruma göre değişebiliyor çünkü. )
Bu kadarı işi çözecektir.
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
Yorumları: 1.664
Konuları: 20
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 19.042 Üstad
21-03-2021, Saat: 22:50
(Son Düzenleme: 21-03-2021, Saat: 23:20, Düzenleyen: mrmarman.)
Katılıyorum, ben de opsioyn 2 olarak verdim zaten. 1 nolu opsiyon zaten candır.
* Sadece her şey senkron yürüyecek deniyorsa veri kaçırmadan yapılması olmazsa olmaz ise, kaçınılmaz olan çoklu thread olur. 15000 microsec işleme 1250 microsec yoksa nasıl handle edilecek...
* Şu da önerilmez; 15 tane thread açık olsun, sürekli resume edilsin. Bu durumda da stabilite bozulur. Bu nedenle yetişmek gerelkiyorsa create / terminate döngüsü bazen kaçınılmaz olabiliyor.
*** Ekleme gereği duyuyorum, stabilite bozulur konusuna takılacaklar olabilir, bir thread açıp bunu handle etmekte zorlanan kişiler, işi biten meşgul olmayan thread hangisi onu tespit et ona iş yükle ve callback ile tetikle vb. işlemlere aşina olmayanlardan kasıt, stabilite o zaman bozulur. Yoksa yapılmayan bir şey değil.
*** Bir ekleme daha yapacağım, bir thread create edilip çalışma anına kadar geçen süresini merak ettim, nette bakındım ve bir yerde 30 milisec sürdüğü konusundaki biri şikayetini yazmış. Deneyip ayrıca bakarız ama bu durumda thread create/ freeonterminate döngüsü opsiyonu çöpe gidiyor. Yetişmez çünkü.
Saygılarımla
Muharrem ARMAN
Yorumları: 902
Konuları: 68
Kayıt Tarihi: 30-06-2017
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 8.392 Üstad
Şu eğitimi inceleyin;
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
Yorumları: 1.460
Konuları: 80
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 11.868 Üstad
Bu gibi sorunlara genellikle "producer/consumer problem" deniliyor. Bu başlık ile arattığınızda pek çok çözüm önerisi elde edebilirsiniz.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
Yorumları: 972
Konuları: 44
Kayıt Tarihi: 24-07-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 2.722 Uzman
Merhaba,
Veriler nasıl? Örnek paylaşabilir misiniz?
Yorumları: 12
Konuları: 3
Kayıt Tarihi: 19-03-2021
Aktif Kullandığınız Delphi Sürümü:
- Delphi 10.3
- Delphi XE Serisi
Rep Puanı: 149 Başlangıç
Merhaba öncelikle cevaplar ve yardımlar için teşekkür ederim.
İlk yazdığım sorunun çözümüne şu şekilde ulaştım. Program ilk çalıştığında bir ana Task ve her Lazer verisi için(16 lazer var) Task array oluşturdum.
FTasks : ITask;
FTasks_Lazer : TArray<ITask>;
procedure TForm_Ana.FormCreate(Sender: TObject);
begin
SetLength(FTasks_Lazer, 16);
end;
ana Task'ı UPD den gelen her 75 paket veride çalıştırdım.
Gelen_Veri_VLP16 := Gelen_Veri_VLP16 + AData;
inc(Veri_Sayaci);
if (IMU_Verileri_Alindi) and (Harita_Guncelleme_Izni) and (Veri_Sayaci = 75) then
begin
Form_Konum_Bilgileri.Label_Nokta_Sayisi.Caption := IntToStr(Sayac_Nokta);
Form_Konum_Bilgileri.Label_Sure.Caption := IntToStr(GetTickCount-Baslangic_Zamani);
try
if Task_Sayaci = 0 then
begin
Baslangic_Zamani := GetTickCount;
Veri_Analizi_Yapildi := False;
Analiz_Verisi := Gelen_Veri_VLP16;
SetLength(Gelen_Veri_VLP16,0);
Veri_Sayaci := 0;
FTasks := TTask.Run(MakeTask(Analiz_Verisi));
FTasks.Wait();
end
else
begin
if TTask.WaitForAll(FTasks_Lazer) and (Veri_Analizi_Yapildi = True) then
begin
Veri_Analizi_Yapildi := False;
Analiz_Verisi := Gelen_Veri_VLP16;
SetLength(Gelen_Veri_VLP16,0);
Veri_Sayaci := 0;
FTasks := TTask.Run(MakeTask(Analiz_Verisi));
FTasks.Wait();
end;
end;
function TForm_Ana.MakeTask(Gelen_Veri_VLP16 : TIdBytes): TProc;
begin
Result :=
procedure
begin
Veri_Analizi_Yap(Gelen_Veri_VLP16);
end;
end;
Veri_Analizi_Yap prosedürünün içinde de her bir lazer için oluşturduğum Task Array çalışıyor. Burada garip bir durumla karşılaştım bu task array için for döngüsü kullandığımda Access Volation hatası ve programda kilitlenme veya tıkanıklık yaşadım, bu yüzden for döngüsü yerine bu şekilde yazmayı tercih ettim. Programı aralıksız 24 saat çalıştırdım ve hiç bir hata almadım.
procedure Lazer_PPL_Calistir(Sayac,I : Integer; Gelen_Veri:TIdBytes; Azimuth :Float32; IMU : TIMU);
begin
FTasks_Lazer[0] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_0(Sayac,I,0,Gelen_Veri,Azimuth,Dikey_Aci[0], IMU);
end);
FTasks_Lazer[1] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_1(Sayac,I,1,Gelen_Veri,Azimuth,Dikey_Aci[1], IMU);
end);
FTasks_Lazer[2] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_2(Sayac,I,2,Gelen_Veri,Azimuth,Dikey_Aci[2], IMU);
end);
FTasks_Lazer[3] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_3(Sayac,I,3,Gelen_Veri,Azimuth,Dikey_Aci[3], IMU);
end);
FTasks_Lazer[4] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_4(Sayac,I,4,Gelen_Veri,Azimuth,Dikey_Aci[4], IMU);
end);
FTasks_Lazer[5] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_5(Sayac,I,5,Gelen_Veri,Azimuth,Dikey_Aci[5], IMU);
end);
FTasks_Lazer[6] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_6(Sayac,I,6,Gelen_Veri,Azimuth,Dikey_Aci[6], IMU);
end);
FTasks_Lazer[7] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_7(Sayac,I,7,Gelen_Veri,Azimuth,Dikey_Aci[7], IMU);
end);
FTasks_Lazer[8] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_8(Sayac,I,8,Gelen_Veri,Azimuth,Dikey_Aci[8], IMU);
end);
FTasks_Lazer[9] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_9(Sayac,I,9,Gelen_Veri,Azimuth,Dikey_Aci[9], IMU);
end);
FTasks_Lazer[10] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_10(Sayac,I,10,Gelen_Veri,Azimuth,Dikey_Aci[10], IMU);
end);
FTasks_Lazer[11] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_11(Sayac,I,11,Gelen_Veri,Azimuth,Dikey_Aci[11], IMU);
end);
FTasks_Lazer[12] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_12(Sayac,I,12,Gelen_Veri,Azimuth,Dikey_Aci[12], IMU);
end);
FTasks_Lazer[13] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_13(Sayac,I,13,Gelen_Veri,Azimuth,Dikey_Aci[13], IMU);
end);
FTasks_Lazer[14] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_14(Sayac,I,14,Gelen_Veri,Azimuth,Dikey_Aci[14], IMU);
end);
FTasks_Lazer[15] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_15(Sayac,I,15,Gelen_Veri,Azimuth,Dikey_Aci[15], IMU);
end);
end;
tekrardan vermiş olduğunuz cevaplar için teşekkür ederim.
Yorumları: 1
Konuları: 0
Kayıt Tarihi: 30-07-2021
Aktif Kullandığınız Delphi Sürümü:
- Delphi 10.3
- Delphi XE Serisi
Rep Puanı: 0 Başlangıç
(28-03-2021, Saat: 14:17)nuheroglu Adlı Kullanıcıdan Alıntı: Merhaba öncelikle cevaplar ve yardımlar için teşekkür ederim.
İlk yazdığım sorunun çözümüne şu şekilde ulaştım. Program ilk çalıştığında bir ana Task ve her Lazer verisi için(16 lazer var) Task array oluşturdum.
FTasks : ITask;
FTasks_Lazer : TArray<ITask>;
procedure TForm_Ana.FormCreate(Sender: TObject);
begin
SetLength(FTasks_Lazer, 16);
end;
ana Task'ı UPD den gelen her 75 paket veride çalıştırdım.
Gelen_Veri_VLP16 := Gelen_Veri_VLP16 + AData;
inc(Veri_Sayaci);
if (IMU_Verileri_Alindi) and (Harita_Guncelleme_Izni) and (Veri_Sayaci = 75) then
begin
Form_Konum_Bilgileri.Label_Nokta_Sayisi.Caption := IntToStr(Sayac_Nokta);
Form_Konum_Bilgileri.Label_Sure.Caption := IntToStr(GetTickCount-Baslangic_Zamani);
try
if Task_Sayaci = 0 then
begin
Baslangic_Zamani := GetTickCount;
Veri_Analizi_Yapildi := False;
Analiz_Verisi := Gelen_Veri_VLP16;
SetLength(Gelen_Veri_VLP16,0);
Veri_Sayaci := 0;
FTasks := TTask.Run(MakeTask(Analiz_Verisi));
FTasks.Wait();
end
else
begin
if TTask.WaitForAll(FTasks_Lazer) and (Veri_Analizi_Yapildi = True) then
begin
Veri_Analizi_Yapildi := False;
Analiz_Verisi := Gelen_Veri_VLP16;
SetLength(Gelen_Veri_VLP16,0);
Veri_Sayaci := 0;
FTasks := TTask.Run(MakeTask(Analiz_Verisi));
FTasks.Wait();
end;
end;
function TForm_Ana.MakeTask(Gelen_Veri_VLP16 : TIdBytes): TProc;
begin
Result :=
procedure
begin
Veri_Analizi_Yap(Gelen_Veri_VLP16);
end;
end;
Veri_Analizi_Yap prosedürünün içinde de her bir lazer için oluşturduğum Task Array çalışıyor. Burada garip bir durumla karşılaştım bu task array için for döngüsü kullandığımda Access Volation hatası ve programda kilitlenme veya tıkanıklık yaşadım, bu yüzden for döngüsü yerine bu şekilde yazmayı tercih ettim. Programı aralıksız 24 saat çalıştırdım ve hiç bir hata almadım.
procedure Lazer_PPL_Calistir(Sayac,I : Integer; Gelen_Veri:TIdBytes; Azimuth :Float32; IMU : TIMU);
begin
FTasks_Lazer[0] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_0(Sayac,I,0,Gelen_Veri,Azimuth,Dikey_Aci[0], IMU);
end);
FTasks_Lazer[1] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_1(Sayac,I,1,Gelen_Veri,Azimuth,Dikey_Aci[1], IMU);
end);
FTasks_Lazer[2] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_2(Sayac,I,2,Gelen_Veri,Azimuth,Dikey_Aci[2], IMU);
end);
FTasks_Lazer[3] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_3(Sayac,I,3,Gelen_Veri,Azimuth,Dikey_Aci[3], IMU);
end);
FTasks_Lazer[4] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_4(Sayac,I,4,Gelen_Veri,Azimuth,Dikey_Aci[4], IMU);
end);
FTasks_Lazer[5] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_5(Sayac,I,5,Gelen_Veri,Azimuth,Dikey_Aci[5], IMU);
end);
FTasks_Lazer[6] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_6(Sayac,I,6,Gelen_Veri,Azimuth,Dikey_Aci[6], IMU);
end);
FTasks_Lazer[7] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_7(Sayac,I,7,Gelen_Veri,Azimuth,Dikey_Aci[7], IMU);
end);
FTasks_Lazer[8] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_8(Sayac,I,8,Gelen_Veri,Azimuth,Dikey_Aci[8], IMU);
end);
FTasks_Lazer[9] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_9(Sayac,I,9,Gelen_Veri,Azimuth,Dikey_Aci[9], IMU);
end);
FTasks_Lazer[10] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_10(Sayac,I,10,Gelen_Veri,Azimuth,Dikey_Aci[10], IMU);
end);
FTasks_Lazer[11] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_11(Sayac,I,11,Gelen_Veri,Azimuth,Dikey_Aci[11], IMU);
end);
FTasks_Lazer[12] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_12(Sayac,I,12,Gelen_Veri,Azimuth,Dikey_Aci[12], IMU);
end);
FTasks_Lazer[13] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_13(Sayac,I,13,Gelen_Veri,Azimuth,Dikey_Aci[13], IMU);
end);
FTasks_Lazer[14] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_14(Sayac,I,14,Gelen_Veri,Azimuth,Dikey_Aci[14], IMU);
end);
FTasks_Lazer[15] := TTask.Run( procedure
begin
Anlik_Verileri_Ciz_15(Sayac,I,15,Gelen_Veri,Azimuth,Dikey_Aci[15], IMU);
end);
end;
tekrardan vermiş olduğunuz cevaplar için teşekkür ederim.
Merhabalar, bende bu yapıya benzer bir yapı ile bir fonksiyon yazdım fakat TTask.Run, içerisine yazılan fonksiyonu sadece bir kere çalıştırmakta, TTask.run'ı sürekli olarak nasıl çalıştırabilirim ?
|