Database Hatası

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
pasa_yasar
Üye
Mesajlar: 570
Kayıt: 07 Haz 2004 12:35

Database Hatası

Mesaj gönderen pasa_yasar »

Mrb.

Uygulama Bilgileri :
Delphi 2007
MySQL 5.5 (x64)
Windows 7 (x64)
Bağlantı Nesnesi : Devart - Unidac 2.6

Hazırladığım programda thread kullandım. Veritabanı bakiye toplamını thread kullanarak arka planda alıyorum. Birkaç kayıt girdikten sonra aşağıdaki hatayı alıyorum. Ortalama 3 - 4 kayıt girdikten sonra.

Resim

Delphiden bağımsız çalıştırdığımda : pure virtual function call hatasıda veriyor bazen

Thread ve Bakiye Hesaplama Kodu :

Kod: Tümünü seç

  private
    { Private declarations }
  public
    { Public declarations }
  end;

 Tfinansbakiyehesaplathread = class (TThread)

  protected
      Procedure Execute ; override;
  end;

var
  finansborc ,finansalacak : real;
    
.
.
.
.
procedure Tfinansbakiyehesaplathread.Execute;
begin

      FreeOnTerminate:=True;

//     Query Toplamları
.
      finansborc := finansborc + UniQueryFinans6.FieldByName('tahsilatlar).AsCurrency;
.
end;

Procedure TForm1.bakiyehesapla;
var
      NewThread: Tfinansbakiyehesaplathread;
begin

      TdxStatusBarTextPanelStyle(dxRibbonStatusBar1.Panels.Items[8].PanelStyle).ImageIndex :=160;
      Application.ProcessMessages;

      NewThread:=Tfinansbakiyehesaplathread.Create(False);

      TdxStatusBarTextPanelStyle(dxRibbonStatusBar1.Panels.Items[8].PanelStyle).ImageIndex :=108;
      Application.ProcessMessages;

      label11.caption:=formatfloat(',0.00;-,0.00',finansborc);
      label12.caption:=formatfloat(',0.00;-,0.00',finansalacak);
      label13.caption:=formatfloat(',0.00;-,0.00',abs(finansborc-finansalacak));

end;

Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Database Hatası

Mesaj gönderen mrmarman »

Hata ile ilgili kısım burada yok.
Access violation senin burada belirtmediğin bir yerde.

Başka bir konu; bakiyehesapla() dediğinde oluşturulan thread sonucuna göre Label11, 12 ve 13 sonucu değişiyor şeklinde görüyorum yanlışım yoksa.

Senin threadinin bitip bitmediğini while NOT NewThread.Terminated do begin .. end; şeklinde bir bekletici unsura ihtiyacın var.

Bunu göremediğimden hatalı olmuş diyebilirim.
Çünkü sen thread execute edildikten hemen sonra, daha erişim sona ermeden bu sonuçları almaya çalışıyorsun.
Resim
Resim ....Resim
Kullanıcı avatarı
pasa_yasar
Üye
Mesajlar: 570
Kayıt: 07 Haz 2004 12:35

Re: Database Hatası

Mesaj gönderen pasa_yasar »

thread bitmeden diğer thread ve işlemlere geçmemeli thread sonucunu beklemeli sanırım. Thread bilgim biraz zayıf bu tür toplamları ve işlemleri yapacağım örnek bir thread yazarmısınız veya link verirseniz inceleme şansım olur.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Database Hatası

Mesaj gönderen mrmarman »

Kendi projende önce söylediğimi bir dene istersen.

Kod: Tümünü seç

...
...
  NewThread:=Tfinansbakiyehesaplathread.Create(False);
  While NOT NewThread.Terminated do
  begin
    Application.ProcessMessages;
    Sleep(1);
  end;
...
...
bu şekilde içerik oluşmadan aşağıdaki kısımlara geçmez...

- Ayrıca thread'e veritabanı olayında neden ihtiyaç duyduğunu açıklarsan belki de başka bir çıkış yolu önerebiliriz. Thread işi VCL ile uyumlu olmayabilir. Bu threadsafe ile ifade edilir. Threadsafe veritabanı bileşeni var mıdır ? Bu konu ayrı bir araştırma konusu. :idea:
Resim
Resim ....Resim
Kullanıcı avatarı
pasa_yasar
Üye
Mesajlar: 570
Kayıt: 07 Haz 2004 12:35

Re: Database Hatası

Mesaj gönderen pasa_yasar »

Kod: Tümünü seç

procedure TMyThread.Execute;
begin
  while not Terminated do begin
    //Here you do a chunk of your work.
    //It's important to have chunks small enough so that "while not Terminated"
    //gets checked often enough.
  end;
  //Here you finalize everything before thread terminates
end;
şeklinde bir kod buldum sanırım kastettiğiniz bu. Bu şekilde kilitlenmezmi bir sorun olduğunda
Kullanıcı avatarı
pasa_yasar
Üye
Mesajlar: 570
Kayıt: 07 Haz 2004 12:35

Re: Database Hatası

Mesaj gönderen pasa_yasar »

Belge,Kart,Bakiye,Stok hesaplarını programı yormadan arka planda hesaplayıp. Online sunucuya göndermek. localdeki bilgileri belirli aralıklarla sunucuya gönderiyor. JvThreadTimer kullandım. 10 sn bir bilgileri sıra ile gönderiyor. gönderdikten sonra Label1,Label2,Label3 olan yerde gönderildiğine veya hesaplandığına dair ekrana bilgi veriyor veya localdeki belgeyi güncelliyor.
Delphi 2007,Mysql 5, Unidac kullanıyorum
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Re: Database Hatası

Mesaj gönderen mrmarman »

Hocam bu veridiğim kod thread'in dışında dikkat edersen.
Yoksa bakiyehesapla procedure'ünü de mi Thread içinde çağırıyorsun ?!

Dışında da olsa kilitlenir ama sen bunun içinde bir timeout koyar, GetTickCount ile mesela 15 saniye geçtiğinde Terminate işlemini döngü içinden de halledersin. Terminate olunca döngüden çıkılır.

TimeOut olduğunu bir Boolean değişkene de yükler, bir if sorgusu ile takip eden bakiye hesabından muaf tutarsın.
En son mrmarman tarafından 21 Eki 2015 02:23 tarihinde düzenlendi, toplamda 1 kere düzenlendi.
Resim
Resim ....Resim
Kullanıcı avatarı
pasa_yasar
Üye
Mesajlar: 570
Kayıt: 07 Haz 2004 12:35

Re: Database Hatası

Mesaj gönderen pasa_yasar »

thread dışında yazdım kodu.
Kullanıcı avatarı
pasa_yasar
Üye
Mesajlar: 570
Kayıt: 07 Haz 2004 12:35

Re: Database Hatası

Mesaj gönderen pasa_yasar »

Bakiye hesabı sorun çıkardığı için soruya cevap gecikince bakiye işlemini sildim sadece aktarımları thread ile yaptım. Ama kodlama aynı Label yerine Query güncelleniyor. Thread içinde güncelleme yapınca hata veriyor threadsafe dolayı herhalde bende thread için aktarım yapıyorum. Aktarım sonucunu göre thread bittiğinde local veritabanını güncelliyorum
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Database Hatası

Mesaj gönderen thelvaci »

İnanılmaz hatalara açık bir kod gözlemliyorum burada ben. Öncelikle thread içinde global bir değişkenin değerine erişiyor ve değiştiriyorsunuz. Eğer illa da bunu yapmak istiyorum diyorsanız; bu durumda InterlockedExchange, InterlockedCompareExchange, InterlockedIncrement vb. kullanmalısınız. İkinci olarak, thread içindeki bazı kodları buraya yazmamışsınız sanırım. Eğer bir thread içinden veritabanına erişimde bulunuyor iseniz; hangi veritabanına erişiyor iseniz o veritabanına bağlanan connection nesnenizi thread içinde oluşturmalı ve bu connection üzerinden ilerlemelisiniz. Bir başka sıkıntı daha; UniQueryFinans6 thread içinde tanımlanan local bir değişken değil ise yine çok ciddi hatalarla karşılaşabilirsiniz.

Kıssadan hisse; thread içinde veritabanı erişimi sağlayacak iseniz, connection sınıfınızı ve query sınıfınız local olarak tanımlayın, create edin kullanın sonra da free edin. CoInitialize/CoUnInitialize kullanmayı da unutmayın eğer bağlantı nesneleriniz COM tabanlı ise. Velhasıl, threading özensiz kodlamayı affetmez, saç baş yolarsınız. Öncelikle sakin kafa ile threading'i öğrenmeli sonra ilerlemelisiniz.

Konu ile alakalı bir kaç makaleyi sitemde bulabilirsiniz.
Kullanıcı avatarı
pasa_yasar
Üye
Mesajlar: 570
Kayıt: 07 Haz 2004 12:35

Re: Database Hatası

Mesaj gönderen pasa_yasar »

Sizin sitenizden inceledim fakat tam hakim olamadım. Rica etsem özet bir örnek yazarmısınız
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: Database Hatası

Mesaj gönderen thelvaci »

Thread tag'i altında bir çok makale ve onlar içinde pek çok da örnek var. Onlar yardımcı olmadı mı ?
Cevapla