Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi [gelöst] Applikation friert ein bei Datenbankzugriff trotz Thread (https://www.delphipraxis.net/162508-%5Bgeloest%5D-applikation-friert-ein-bei-datenbankzugriff-trotz-thread.html)

Tonic1024 25. Aug 2011 15:40

Datenbank: Firebird • Version: 2.1 • Zugriff über: Zeos 7

[gelöst] Applikation friert ein bei Datenbankzugriff trotz Thread
 
Hallo...

Mein Kollege kam zu mir weil seine Datenbankanwendung zyklisch sekundenweise einfriert. Beim debuggen hab ich dann schnell herausgefunden, dass die Datenbankabfragen die Ursache dafür sind. Klarer Fall. Das muss gethreadded werden.

Doch auch mit Thread friert meine kleine Sandbox ein. Wie kann das denn angehen?

Bissl (unfertiger) Code:
Delphi-Quellcode:
type
  TUpdater = class(TThread)
  private
    FCnx: TZConnection;
    FQry: TZQuery;

    FCS: TCriticalSection;
    FRepository: CRepository;
    FObjects: TObjectList;
    FTable: String;
    FKlausel: String;

    destructor destroy;
  protected
    procedure Execute; override;
  public
    constructor create(CreateSuspended: Boolean);
  end;
Delphi-Quellcode:
procedure TUpdater.Execute;
var Instance: TKMicsRepository;
begin
  CoInitialize(nil); // Hab ich nach der Forensuche eingebaut - hat nichts bewirkt
  FQry.SQL.Clear;
  FQry.SQL.Add('SELECT * FROM '+FTable);

  if FKlausel <> '' then
    FQry.SQL.Add('WHERE '+FKlausel);

// Alles mögliche auskommentiert - friert trotzdem immernoch kurz ein...
//  if Assigned(FCS) then
//    FCS.Enter;
  try
    FQry.Open;
//    FObjects.Clear;
    while not FQry.Eof do // ... und zwar genau hier
    begin
//      Instance:=CRepository(FRepository).Create;
//      Instance.readValue(FQry.Fields);
//      FObjects.Add(Instance);
      FQry.Next;
    end;
  finally
//    if Assigned(FCS) then
//      FCS.Leave;
  end;
  FQry.Close;
  FCnx.Disconnect;
  CoUnInitialize;
  Self.Terminate;
end;

constructor TUpdater.create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);

  FCnx:=TZConnection.Create(nil);
  FCnx.Protocol:= 'firebird-2.1';
  FCnx.HostName:= '192.168.200.5';
  FCnx.Database:= 'c:\firebird\test2.fdb';
  FCnx.User:= 'sysdba';
  FCnx.Password:= 'masterkey';
  FCnx.Properties.Clear;
  {..}

  FQry:=TZQuery.Create(nil);
  FQry.Properties.Clear;
  {..}
  FQry.Connection:=FCnx;
end;

destructor TUpdater.destroy;
begin
  freeAndNil(FCnx);
  freeAndNil(FQry);

  inherited Destroy;
end;
Delphi-Quellcode:
procedure TCachingTable.refresh;
var Updater: TUpdater;
begin
  Updater:=TUpdater.Create(true);
  Updater.FreeOnTerminate:=true;
  Updater.FCS:=FCS;
  Updater.FTable:=FTable;
  Updater.FKlausel:=FKlausel;
  Updater.FRepository:=FRepository;
  Updater.FObjects:=FObjects;
  Updater.Resume;

  while not Updater.Finished do
    Application.ProcessMessages;

  if Assigned(doUpdate) then
    doUpdate(self);
end;
Jemand noch ne Idee was das sein kann?

Gruß,

Toni

DeddyH 25. Aug 2011 15:50

AW: Applikation friert ein bei Datenbankzugriff trotz Thread
 
Zitat:

Zitat von Tonic1024 (Beitrag 1119637)
Delphi-Quellcode:
  while not Updater.Finished do
    Application.ProcessMessages;

Ein Thread und ProcessMessages? Das sieht zumindest ungewöhnlich aus. Wie wäre es denn mit synchronisierten Events?

Tonic1024 25. Aug 2011 15:55

AW: Applikation friert ein bei Datenbankzugriff trotz Thread
 
Naja, er soll ja ausschließlich die Usereingaben weiter ausführen. Ich hielt das für zweckmäßig. zu syncen gibts da nix. Es geht während er läuft (also zwischen Resume und Terminate) nix rein und nix raus.

[Edit]
Es geht mir nur darum während eines Datenbankzugriffs im Frontend Scrollbars bedienen zu können. In meiner Sandbox hab ich eine Combobox mit 200 Einträgen, die ich mit der Maus hoch und runter scrolle.
[/Edit]

himitsu 25. Aug 2011 16:28

AW: Applikation friert ein bei Datenbankzugriff trotz Thread
 
Es geht darum, daß man in fremden Threads auf keine VCL-Dinge zugreift (außer man synchronisiert diese Zugriffe in den Hauptthread)

Und ProcessMessages hat in Threads sowieso nichts zu suchen.

generic 25. Aug 2011 16:30

AW: Applikation friert ein bei Datenbankzugriff trotz Thread
 
Delphi-Quellcode:
while not Updater.Finished do
    Application.ProcessMessages;
das lass mal besser weg und reagiere auf das onThreadTerminate-Ereignis

defede 25. Aug 2011 18:11

AW: Applikation friert ein bei Datenbankzugriff trotz Thread
 
Hi,
du gehst die Datenmenge ja einmal komplett durch?
Naja ich würde nach dem Open in dem Fall erstmal ein First machen vll hilft das?
Amsonsten fallen mir nur noch sowas wie Events ein die dran hängen
oder sowas wie CalcFields, weiss leider nicht wie dein FQry aussieht.
Delphi-Quellcode:
    while not FQry.Eof do// ... und zwar genau hier
     begin
 // Instance:=CRepository(FRepository).Create;
 // Instance.readValue(FQry.Fields);
 // FObjects.Add(Instance);
       FQry.Next;
     end;

Tonic1024 26. Aug 2011 07:48

AW: Applikation friert ein bei Datenbankzugriff trotz Thread
 
Guten Morgen.

@himitsu: Das ist nicht IM Thread sondern eher außen herum in der GUI.

Hab das gestern nicht mehr geschafft auszuprobieren. Aber mit onTerminate klappts. Vielen Dank für den Hinweis. Unter D7 war das nie ein Problem. Ist das neu?

Gruß,

Toni

sirius 26. Aug 2011 08:06

AW: Applikation friert ein bei Datenbankzugriff trotz Thread
 
Du darfst bei Threads nicht wie üblich die (bzw. bestimmte) Felder im constructor initialisieren, sondern du darsft das erst in Execute. Hier geht es hauptsächlich um die DB-Kompos.

VErsuch dir folgende Strucktur anzugewöhnen:
Delphi-Quellcode:
procedure Tupdater.execute;
begin
  ConInitialize(nil);
  myConnection:=TxyzConnection.Create(...);
  myQuery:=...
  try
    eigentlicher_Thread_execute;
  finally
    myQuery.free;
    myConnection.free;
    coUninitialize;
  end;
end;
procedure Tupdater.eigentlicher_thread_execute;
begin
  ...
end;
Edit: Und die letzten 4 Zeilen in Refresh nimmst du bitte auch raus und löst das anders!
Es gibt z.B. das Ereignis onTerminate, dass du zuweisen kannst (auf doUpdate).

Tonic1024 26. Aug 2011 08:17

AW: Applikation friert ein bei Datenbankzugriff trotz Thread
 
Zitat:

Zitat von sirius (Beitrag 1119739)
Edit: Und die letzten 4 Zeilen in Refresh nimmst du bitte auch raus und löst das anders!
Es gibt z.B. das Ereignis onTerminate, dass du zuweisen kannst (auf doUpdate).

Das war auch das Problem, wie ich oben geschildert hab. Und weil ich immer gern verstehe warum Dinge so sind wie sie sind, hatte ich nach dem Warum gefragt.

Toni


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:47 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz