Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi MySQL-Abfrage in Thread verpackt, trotzdem Programmbremse (https://www.delphipraxis.net/126964-mysql-abfrage-thread-verpackt-trotzdem-programmbremse.html)

christian_r 5. Jan 2009 20:30


MySQL-Abfrage in Thread verpackt, trotzdem Programmbremse
 
Ich habe eine permanente MySQL-Abfrage für mein Remote-Tool. Diese habe ich daher in einen Thread verpackt.
Ich verwende die Komponentensammlung "MySQL Direct".

Meine Tests liefen über die MySQL-Verbindung zu meinem "localhost" sehr flüssig. Nachdem ich nun eine Verbindung zu meinem Server online aufbaue, bremst die MySQL-Query das Programm trotz allem aus.

Delphi-Quellcode:
type
  TForm1 = Class( TForm )
    ThreadCommand : TThreadCommand;
    MySQL        : TOMySQL; // Ein Wrapper für 'TMySQLClient' von MySQL Direct
  end;

// ...

Self.ThreadCommand                := TOThreadCommandOrder.Create( True );
Self.ThreadCommand.FreeOnTerminate := True;
Self.ThreadCommand.Priority       := tpNormal;
Self.ThreadCommand.MySQL          := Self.MySQL;

// ...

procedure TThreadCommand.ProcessCommand
          (  );
var
  MySQLResult : TOMySQLResult; // Ein Wrapper für 'TMySQLResult' von MySQL Direct
begin
  if Assigned( Self.MySQL ) then
  begin
    MySQLResult := Self.MySQL.Query( 'SELECT * FROM `ubig_orders` LIMIT 0, 1' );
    // ...
  end;
end;
Ich kann versichern, dass das Problem nicht an den Wrappern für die MySQL-Klassen liegt. Ich habe den Quellcode in den Wrapper geprüft und festgestellt, dass der Aufruf von TMySQLClient.Query( ) bereits ausbremst.

Liegt es nun an meiner Art und Weise den Thread zu verwenden, was ich mir nicht vorstellen kann. Oder ist die MySQL Direct Komponente problematisch? Normalerweise sollte ich doch von dem Prozess im Thread nichts mitbekommen.

christian_r 6. Jan 2009 11:43

Re: MySQL-Abfrage in Thread verpackt, trotzdem Programmbrems
 
Sorry, ich habe "TThreadCommand.Execute()" vergessen. Also ProcessCommand wird synchronisiert.

Delphi-Quellcode:
procedure TThreadCommand.Execute
          (  );
begin
  while not Self.Terminated do
    Self.Synchronize( Self.ProcessCommand );
end;

quendolineDD 6. Jan 2009 19:12

Re: MySQL-Abfrage in Thread verpackt, trotzdem Programmbrems
 
Wenn du alles über Synchronize aufrufst, wird auch alles über den Hauptthread berechnet. Deswegen ist es auch eine "Bremse".

sirius 6. Jan 2009 19:19

Re: MySQL-Abfrage in Thread verpackt, trotzdem Programmbrems
 
Hier bringt der Thread null und nix. Du solltest außerhalb von synchronize arbeiten. Dazu musst du aber alles, was SQL betrifft in den Thread legen.

christian_r 9. Jan 2009 07:29

Re: MySQL-Abfrage in Thread verpackt, trotzdem Programmbrems
 
Danke Euch. Läuft jetzt.

Und stimmt. Der Prozess des Programmes selbst verbaucht keine 50% mehr. Alles flüssiger.

christian_r 9. Jan 2009 10:35

Re: MySQL-Abfrage in Thread verpackt, trotzdem Programmbrems
 
Eine abschließende Frage zu diesem Thema.

Wenn ich im Hauptprogramm in "TForm.Destroy()" den Thread mit "Self.ThreadCommand.Terminate()" beende, wird jedesmal eine Exception explizit innerhalb des MySQL-Objektes von MySQL Direct (nicht im MySQL-Wrapper) ausgelöst. Alle anderen Objekte, wie z. B. das Log oder der CommandWrapper, verursachen keine Exception. Ich muss den Thread jedesmal vorher suspendieren, was ich jetzt mit einer überschriebenen Methode "TThreadCommand.Terminate()" gelöst habe.

Woran kann das liegen? Die Objekte, die ich dem Thread übergebe, werden nicht im Thread zerstört, sondern im Hauptprogramm.

Ja, die Frage ist vage, sofern ihr auch die Quellcodes nicht kennt. Aber vllt. kennt jemand dieses Problem brerits, oder kennt die Funktionsweise von MySQL-Direct.

sirius 9. Jan 2009 10:44

Re: MySQL-Abfrage in Thread verpackt, trotzdem Programmbrems
 
Du übergibst dem Thread Objekte? Das geht schief. Und zwar meist erst beim Kunden und dann immer zufällig.

Ich nehme (ohne Quelltext) an, du hast nicht die gesamte DB-Arbeit in den Thread gelegt sondern übergibst nur die Query. Das geht so nicht. Du musst den Thread vom Hauptprogramm komplett trennen und im Nachhinein überlegen, welche Schnittstellen zwischen beiden notwnedig sind.

Also hier heißt es alle Datenbankkomponenten in den Thread.

christian_r 9. Jan 2009 12:02

Re: MySQL-Abfrage in Thread verpackt, trotzdem Programmbrems
 
Hm ...

Meine bisherige Überlegung war, dass der Thread eine MySQL-Verbindung übergeben bekommt, die im Haupthread instanziert wird. Somit kann ich zukünftig parralel laufenden Threads ein und dasselbe DB-Objekt übergeben und muss nicht 10 verschiedene Verbindungn aufbauen. Aber ... hm ... jetzt klickt es so langsam. Wenn ich dann natürlich 10 Threads auf ein und dieselbe Instanz gleichzeitig zugreifen lasse könnte es Probleme geben, die ich jetzt noch nicht absehen kann.

Können zwei Threads gleichzeitig auf ein und die selbe Methode von ein und der selben Instanz eines Objektes zugreifen ohne Probleme zu verursachen?

Ich verstehe grad noch nicht so richtig, warum ich den Thread komplett "eigenständiug" konstruieren muss. Welche Probleme gibt es sonst, außer dem, welches ich hier beschrieben hatte?

sirius 9. Jan 2009 13:12

Re: MySQL-Abfrage in Thread verpackt, trotzdem Programmbrems
 
Wenn du parrallel mit der Datenbank arbeiten willst, brauchst du IMHO sowieso mehrere Datenbankverbindungen. Also dann jeweils eine pro Thread (aber zuviele aktive Threads verträgt das System eh nicht).

Ich mach es immer so, dass ich in meinen Projekten ein Thread habe der nur für die Kommunikation mit der Datenbank zuständig ist. Und auch nur dieser Thread ist mit der Datenbank verbunden. Da sind alle Komponenten für die Datenbank enthalten, die ich benötige. Und dieser Thread schläft meistens, bis ich ihm eine neue Aufgabe über eine Liste (bspw: TThreadList) gebe. Die erledigt er und gibt mir im Anschluss das Ergebnis.

Zitat:

Können zwei Threads gleichzeitig auf ein und die selbe Methode von ein und der selben Instanz eines Objektes zugreifen ohne Probleme zu verursachen?
Riesenprobleme (wegen derselben Instanz, selbe Methode wäre kein Problem). Du greifst u.U gleichzeitg auf eine Variable/Feld zu. Such mal hier im Forum, da gibt es viele Aussagen dazu.

christian_r 9. Jan 2009 13:24

Re: MySQL-Abfrage in Thread verpackt, trotzdem Programmbrems
 
OK, jetzt bildet sich so langsam ein klares Bild, auch im Zusammenhang mit dem WorkersThread. Und an die überschneidenden Zugriffe hatte ich bei meiner Konzeption erst gar nicht gedacht.

Danke. Soweit kann ich nun erst mal weiterarbeiten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:19 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