Merhaba,
Öncelikle mevcut kod ile ilgili bir iki noktaya dikkat çekmek istiyorum.
1- Ana form içindeki kodunuzda hafıza kaçağı var. Create edilen FDQuery nesnesi Free edilmemiş.
2- Form2 içindeki kodunuzda da hafıza kaçağı mevcut. Yine create edilen FDQuery nesnesi Free edilmemiş.
3- Mümkün olduğunca
"with" ifadesini kullanmaktan kaçının. Kodu karmaşıklaştırır.
4- Mümkünse hiçbir zaman
"with TFDQuery.Create(nil) do" şeklinde bir kod yazmayın. Bunun yerine değişken tanımlayarak. Bu değişkene yeni create edilen bir TFDQuery nesnesini atayarak ve try..finally bloğu içinde kod yazmaya gayret edin. Form2 için yazmış olduğunuz kod aşağıdaki gibi yazılabilir. Böylece hafıza kaçağını önlemiş olursunuz
Kod: Tümünü seç
procedure TForm2.HatirlatmaListele(Sender: TObject);
var
Query: TFDQuery;
begin
Query := TFDQuery.Create(nil);
try
Query.Connection := ANAForm.GenelConnection;
Query.SQL.Add('Select * From HATIRLATMA');
Query.SQL.Add('Order By TARIH ASC, SAAT');
Query.SQL.Add('Limit 0,100');
Query.Prepared := True;
Query.Open();
Query.First();
ListViewHT.Items.BeginUpdate();
try
ListViewHT.Items.Clear();
while Not Query.Eof do
begin
with ListViewHT.Items.Add do
begin
Caption := IntToStr(Query.FieldByName('ID').AsInteger);
SubItems.Add(Query.FieldByName('TARIH').AsString);
SubItems.Add(Copy(Query.FieldByName('SAAT').AsString, 1, 5));
SubItems.Add(Query.FieldByName('HATIRLATMAMESAJI').AsString);
SubItems.Add(Query.FieldByName('DURUM').AsString);
Query.Next();
end;
end;
finally
ListViewHT.Items.EndUpdate();
end;
finally
Query.Free();
end;
end;
Kod yazma alışkanlığınıza istinaden projenizde başka yerde/yerlerde de hafıza kaçağı olabileceğini düşünüyorum. Bu anlamda kodunuzu incelemenizde fayda var. Uygulamada hafıza kaçağı kontrolü için Project->View Source kısmına gelerek gelen kod ekranında begin ifadesinin hemen altına
Kod: Tümünü seç
ReportMemoryLeaksOnShutdown := True;
ifadesini eklemeniz yeterli. Bu durumda
uygulama tamamen kapatıldığı zaman hafıza kaçağı varsa eğer ekrana bunu gösteren bir mesaj gelecektir. Hafıza kaçağı yoksa herhangi bir mesaj gelmez. Ancak bu şekilde uygulama içinde girip çıktığınız tüm ekranlardaki tüm kaçaklar listelenecektir. Bu anlamda nereleri açıp kapattığınızı veya tıkladığınızı hatırlamanız, her defasında sadece bir formu kontrol etmeniz ve sorun yok ise diğer forma geçmeniz gerekebilir.
Esas sorunuza gelince:
A- Database içinde hatırlatma tarih ve saati saklandığı yazılan kod içinden anlaşılıyor. Kullanıcı bir kayıt ekleyip daha sonra bu kayda ait tarih ve/veya saati değiştirdiğini düşünün. Eğer database kopyasını hafızada tutar iseniz bu durumda yanlış zamanda hatırlatma yapmış olursunuz.
Diğer bir olasılık ise; kullanıcı bir hatırlatma ekledi. Uygulama hatırlatmaları hafızaya aldı. Daha sonra kullanıcı bir hatırlatma daha ekledi. Üstelik bu ikinci eklediği hatırlatmayı daha yakın bir zaman için ekledi. Uygulama bu durumda da hatırlatma olmasına rağmen ekranda göstermiyor olabilir. Bu anlamda her kontrol zamanında hatırlatma mesajlarını database'den sorgulamak en doğrusu olacaktır.
B- Database sisteminin sürekli sorgulanmasını engellemek adına hatırlatma zamanlarını kayıt esnasında 15 dakika aralıklar ile (0, 15, 30, 45nci dakikalar gibi) yapılmasını zorlar iseniz Timer sadece 15 dakikada bir çalışabilir. Bu da sistem ve database yükünü oldukça azaltacaktır. Eğer 15 dakika uzun ise 10 veya 5 dakikalık aralıkları zolayabilirsiniz. Diğer taraftan 15 dakikanın oldukça yeterli olacağını düşünüyorum. Unutulmamalıdır ki sürekli çalışan ve/veya internet bağantısına sahip bilgisayar saatleri dahi birkaç dakikalık fark ile çalışabilmektedir (Anlık dahi olsa CPU yoğunluğu sistem saatinin normalden azar azar sapmasına sebep olur). Her halukarda saniyelik kontrol yapılmasına gerek olmayacaktır. Yazılan kod saniyelik kısımları kontrol etmiyor.
C- Kontrol yapılacak kodu (OnTimer içine yazılan kod) yazarken tüm kaytıları listelemek yerine sadece zamanı gelmiş ve geçmiş kayıtları listeler iseniz database üzerinden okunacak veri çok daha az ve işlem daha hızlı olacaktır. Bununla birlikte eğer eski mesajlar önemli değil ise tablodan silinmeleri, önemli ise farklı bir tablo/database içine arşivlenmeleri sorgu performansını artıracaktır.
D- Performansı birazcık daha artırmak adına kontrol için kullanılan Query form üzerinde dizayn aşamasında oluşturulup sadece parametreleri değiştirilerek çalıştırılabilir. Böylece her OnTimer çalıştığında TFDQuery nesnesi oluşturmasına gerek kalmayıp prosesin daha çabuk bitmesini sağlayabilirsiniz.
Yukarıdaki tavsiyeler göz önünde bulundurularak aşağıdaki gibi bir kod yazmak mümkün olabilir.
Ana form create kısmına yazılacak kod (form üzerinde MessageCheckQuery adında bir FDQuery nesnesi olduğunu varsayıyor)
Kod: Tümünü seç
procedure TANAForm.FormCreate(Sender: TObject);
begin
MessageCheckQuery.Close();
MessageCheckQuery.Connection := GenelConnection;
MessageCheckQuery.SQL.Clear();
MessageCheckQuery.SQL.Add('Select * From HATIRLATMA');
MessageCheckQuery.SQL.Add('where Tarih <= :Tarih and Saat <= :Saat');
MessageCheckQuery.SQL.Add('and DURUM=''Yeni''');
MessageCheckQuery.Prepared := True;
end;
Timer kısmına yazılacak kod
Kod: Tümünü seç
procedure TANAForm.TimerHatirlatmaTimer(Sender: TObject);
var
ControlTime: TDateTime;
begin
// Kontrol başlat başlamaz Timer durdurulmalı
TimerHatirlatma.Enabled := False;
ControlTime := now;
MessageCheckQuery.Close();
MessageCheckQuery.Params[0].AsDate := DateOf(ControlTime);
MessageCheckQuery.Params[1].AsTime := TimeOf(ControlTime);
MessageCheckQuery.Open();
if MessageCheckQuery.RecordCount > 0 then
begin
MessageCheckQuery.First();
while not MessageCheckQuery.Eof do
begin
// Her bir hatırlatma için tek tek ekrana mesajları göster
ImageMesaj.Visible := True;
MessageCheckQuery.Next();
end;
end;
MessageCheckQuery.Close();
TimerHatirlatma.Enabled := True;
end;