AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi SQL Query in Thread wie Datenrückgabe realisieren

SQL Query in Thread wie Datenrückgabe realisieren

Ein Thema von stOrM · begonnen am 11. Okt 2016 · letzter Beitrag vom 14. Okt 2016
Antwort Antwort
Seite 2 von 3     12 3   
nahpets
(Gast)

n/a Beiträge
 
#11

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 15:48
Was mich noch interessieren würde:

Muss man die VirtualTable vor der Datenübernahme nicht schließen und nach der Zuweisung auf DataSource nicht öffnen?

Sprich: Bekommt man bei FVirtualTable.Assign(FUniDacSQLQuery); 'ne offene Datenmenge zurück?
Delphi-Quellcode:
procedure TView.btnStartClick(Sender: TObject);
begin
  UniDataSource1.DataSet.DisableControls;
  UniDataSource1.DataSet.Close;
  DBGrid1.DataSource := Nil;
  UniDataSource1.DataSet := Nil;
  // I know this will leak at the moment!
  FSQLThrd := TSqlQueryThrd.Create(self.Handle, edtConStr.Text, edtSqlTxt.Text, VirtualTable1);
  try
    FSQLThrd.FreeOnTerminate := false;
    FSQLThrd.Start;
  except
  on E: Exception do
    MSGLog.Lines.Text := E.Message;
  end;
end;

procedure TView.OnThreadQueryDone(
  const ThreadQueryDoneMsgPtr: PThreadQueryDoneMsg);
begin
  case ThreadQueryDoneMsgPtr^.Done of
   true:
   begin
     QrPB.State := pbsPaused;
     try
       UniDataSource1.DataSet.DisableControls;
       UniDataSource1.DataSet := VirtualTable1;
       DBGrid1.DataSource := UniDataSource1;
       UniDataSource1.DataSet.Open;
     finally
       // Das würd' ich nur machen, wenn's vorher keine Exception gab.
       UniDataSource1.DataSet.EnableControls;
     end;
   end;
   false: QrPB.State := pbsNormal;
  end;
   Dispose(ThreadQueryDoneMsgPtr);
end;
  Mit Zitat antworten Zitat
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
673 Beiträge
 
Delphi 10.4 Sydney
 
#12

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 15:52
Zitat:
Das kann ich nachvollziehen, allerdings hätte ich erwartet, dass vor dem Start des Thread eben gerade diese Verbindung aufgehoben wird.
Das kann sollte ich vielleicht mal testen. Zumindest wäre das sinnvoll, Beim OnCreate des Formulars ist alles noch ungebunden, aber wenn der separate Thread gestartet wurde nicht mehr, ich ändere das mal ab.
Das meinte ich mit

Zitat:
aber erst der Datasource zuweisen, wenn der Thread fertig ist, sonst versucht das grid die schon zu lesen während du sie noch befüllst.
Was wir immer machen ist auf den ButtonClick immer erstmal den Button abschalten (Enabled := False) und erst wieder anschalten, wenn wir fertig sind mit unserem Code.

Auch Dein RecordCount wird eventuell falsch sein, da UniQuery die Zahl anzeigt, die sie erstmal holen (default 25). Entweder musst Du QueryRecordCount property setzen (macht uniquery dann 2x das Query, einmal zum zählen und ein 2. Mal um die ersten Daten zu holen).
Ich empfehle einfach den RecordCount der VirtualTable nach dem Assign zu nutzen. Aber da beendest Du den Thread eh und du kannst im MainThread einfach den RecordCount der VT zu fragen.


@nahpets : ich glaube, es spielt keine Rolle, da VT eh das dataset schliessen muss um die Field Liste zu löschen, da die ja von DataSet übernommen wird. Und der VT sollte dann automatisch geöffnet werden. Aber das kann man ja überprüfen mit

Code:
If Not VT.State in dsBrowsing Then
  Mit Zitat antworten Zitat
Benutzerbild von stOrM
stOrM

Registriert seit: 7. Jun 2003
Ort: Mülheim an der Ruhr
434 Beiträge
 
Delphi 10.3 Rio
 
#13

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 15:58
Zitat:
Das kann ich nachvollziehen, allerdings hätte ich erwartet, dass vor dem Start des Thread eben gerade diese Verbindung aufgehoben wird.
Das kann sollte ich vielleicht mal testen. Zumindest wäre das sinnvoll, Beim OnCreate des Formulars ist alles noch ungebunden, aber wenn der separate Thread gestartet wurde nicht mehr, ich ändere das mal ab.
Das meinte ich mit

Zitat:
aber erst der Datasource zuweisen, wenn der Thread fertig ist, sonst versucht das grid die schon zu lesen während du sie noch befüllst.
Was wir immer machen ist auf den ButtonClick immer erstmal den Button abschalten (Enabled := False) und erst wieder anschalten, wenn wir fertig sind mit unserem Code.

Auch Dein RecordCount wird eventuell falsch sein, da UniQuery die Zahl anzeigt, die sie erstmal holen (default 25). Entweder musst Du QueryRecordCount property setzen (macht uniquery dann 2x das Query, einmal zum zählen und ein 2. Mal um die ersten Daten zu holen).
Ich empfehle einfach den RecordCount der VirtualTable nach dem Assign zu nutzen. Aber da beendest Du den Thread eh und du kannst im MainThread einfach den RecordCount der VT zu fragen.


@nahpets : ich glaube, es spielt keine Rolle, da VT eh das dataset schliessen muss um die Field Liste zu löschen, da die ja von DataSet übernommen wird. Und der VT sollte dann automatisch geöffnet werden. Aber das kann man ja überprüfen mit

Code:
If Not VT.State in dsBrowsing Then
Ich hab die Änderungen jetzt soweit eingebaut, ändert aber nichts an der Fehlermeldung mit dem Canvas.
Teilweise bekomme ich sogar noch folgendes: VCL.Grids stop in Zeile 888 GridIndex ausserhalb des gültigen Bereichs (mal was neues)

Was den RecordCount angeht denke ich nicht das dieser falsch ist, ich setze beim Query explizit FetchAll also soll lt. Doku alles an Daten geholt werden und nicht nur partiell.


Zitat:
Ich empfehle einfach den RecordCount der VirtualTable nach dem Assign zu nutzen.
Wenn das funktionieren würde hätte ich das getan, deshalb der Umweg über die Messages. Der RecordCount im Main bei der VT ist nämlich immer 0 bei mir mit dem Query gehts einwandfrei.
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.123 Beiträge
 
Delphi 10.3 Rio
 
#14

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 16:06
Warum nimmst Du die Windows MessageQue und nicht System.Messaging?
Dann kannst Du dir auch das ganze Pointer-Zeug sparen.

Warum nimmst Du eine TThread Klasse und nicht System.Threading?

Eine eigene Threadklasse nutze ich nur noch, wenn ich den Thread 1x Erzeuge und behalte...
Zum Beispiel um mit einen SetEvent(StartEvent) die Verarbeitung in Nano-Sekundenbereich beginnen zu lassen. Zum Beispiel,
wenn von der Eingangsqueue ein neuer SQL-Befehlt kommt.

Vorgehen:
- Ich gebe die SQL-Befehle in die ThreadSaveQueue. Bei Eingang wir der Event gefeuert und der Thread läuft sofort los.
- ich kann jederzeit neue Befehle in die Queue feuern und die werden nacheinander abgearbeitet.
- Der Thread erzeugt die Daten und packt diese in einen Ausgang-Queue. Damit ist der Thread frei für weitere Aufgaben.
- Da ich der Eingangsqueue eine anonyme Procedure mitgegeben habe, kann die Ausgangsqueue in einem 2. Thread nach und nach die Syncronize der anonymen Proceduren aufrufen, die die Daten in der UI darstellen.

Natürlich kann man das über die System.Threading auch machen! Ich nutze jedoch eine TThread-Klasse, da ich hierüber den MultiThread-Zugriff auf eine SQLite Datenbank serialisiere!

Wenn ich mit MultiThread/MultiConnectionfähigen Datenbanken arbeite, nutze ich natürlich den ThreadPool, um so viele Anfragen wie möglich gleichzeitig zu handeln und die Skalierbarkeit des Datenbankservers auszunutzen.

Mavarik
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#15

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 16:08
Ich hab die Änderungen jetzt soweit eingebaut, ändert aber nichts an der Fehlermeldung mit dem Canvas.
Teilweise bekomme ich sogar noch folgendes: VCL.Grids stop in Zeile 888 GridIndex ausserhalb des gültigen Bereichs (mal was neues)
Das erinnert mit an den ungültigen Gitterindex bei StringGrids.
Das passiert, wenn man auf 'ne Zelle, Spalte, Zeile zugfreift, die es nicht (mehr) gibt.

Kann in dem Zusammenhang mit DBGrids passieren, wenn die Spaltenzahl der aktuellen Datenmenge nicht mit der der vorherigen übereinstimmt, das Grid aber trotzdem versucht die Daten einzulesen.

Schau mal bitte, ob Dein Grid sowas in der Art kennt:
Delphi-Quellcode:
DBGrid.Fields.Clear;
DBGrid.Columns.Clear;
(Eigentlich braucht man sowas ja nicht, aber manchmal doch )
Wenn ja, bau das nach dem Entfernen der Datasource noch ein oder vor der Zuweisung der Datasource, wenn Du die befüllte VT bekommst.
  Mit Zitat antworten Zitat
Benutzerbild von stOrM
stOrM

Registriert seit: 7. Jun 2003
Ort: Mülheim an der Ruhr
434 Beiträge
 
Delphi 10.3 Rio
 
#16

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 16:13
Ich hab die Änderungen jetzt soweit eingebaut, ändert aber nichts an der Fehlermeldung mit dem Canvas.
Teilweise bekomme ich sogar noch folgendes: VCL.Grids stop in Zeile 888 GridIndex ausserhalb des gültigen Bereichs (mal was neues)
Das erinnert mit an den ungültigen Gitterindex bei StringGrids.
Das passiert, wenn man auf 'ne Zelle, Spalte, Zeile zugfreift, die es nicht (mehr) gibt.

Kann in dem Zusammenhang mit DBGrids passieren, wenn die Spaltenzahl der aktuellen Datenmenge nicht mit der der vorherigen übereinstimmt, das Grid aber trotzdem versucht die Daten einzulesen.

Schau mal bitte, ob Dein Grid sowas in der Art kennt:
Delphi-Quellcode:
DBGrid.Fields.Clear;
DBGrid.Columns.Clear;
(Eigentlich braucht man sowas ja nicht, aber manchmal doch )
Wenn ja, bau das nach dem Entfernen der Datasource noch ein oder vor der Zuweisung der Datasource, wenn Du die befüllte VT bekommst.
Jep Columns.Clear gibt es bau ich mal ein, dass Canvas Problem bleibt aber wie gehabt komischerweise tritt es eher Random ein.

Also keine Ahnung was das Problem ist, ich hab jetzt im ButtonClick noch extra folgendes eingebaut zur Sicherheit, ändert weiterhin nichts an den Exceptions:

Code:
  DBGrid1.Columns.Clear;
  VirtualTable1.Open;
  VirtualTable1.Edit;
  VirtualTable1.ClearFields;
  VirtualTable1.Close;
  DBGrid1.DataSource := Nil;

Geändert von stOrM (13. Okt 2016 um 16:32 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
673 Beiträge
 
Delphi 10.4 Sydney
 
#17

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 17:04
Ich habe Dir mal schnell deins umgebaut, so dass es geht.
Die Zwischennachrichten abgeschaltet, wichtig ist ja erstmal, dass es überhaupt fehlerfrei läuft.

Nach dem Start des Threads wird nicht mehr auf die VT zugegriffen bis zum (neu implementierten) OnTerminate event. Die VT ist da noch geschlossen, von daher der Check aufs VirtualTable.Active.

Den Provider musst imm Thread nicht setzen, der ist im ConnectionString.
Musst ihn mal auf MySQL setzen wieder, ich habe nur Firebird installiert.


Ich habe den thread mehrfach ausgeführt ohne Fehler im Grid (nutze Delphi 10.1 Upd1), auch das Programm mehrfach, konte aber den Fehler nicht feststellen, den Du erwähntest.

Viel Spass
Helge
Angehängte Dateien
Dateityp: zip QueryThread_DP.zip (55,7 KB, 19x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von stOrM
stOrM

Registriert seit: 7. Jun 2003
Ort: Mülheim an der Ruhr
434 Beiträge
 
Delphi 10.3 Rio
 
#18

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 17:07
Ich habe Dir mal schnell deins umgebaut, so dass es geht.
Die Zwischennachrichten abgeschaltet, wichtig ist ja erstmal, dass es überhaupt fehlerfrei läuft.

Nach dem Start des Threads wird nicht mehr auf die VT zugegriffen bis zum (neu implementierten) OnTerminate event. Die VT ist da noch geschlossen, von daher der Check aufs VirtualTable.Active.

Den Provider musst imm Thread nicht setzen, der ist im ConnectionString.
Musst ihn mal auf MySQL setzen wieder, ich habe nur Firebird installiert.


Ich habe den thread mehrfach ausgeführt ohne Fehler im Grid (nutze Delphi 10.1 Upd1), auch das Programm mehrfach, konte aber den Fehler nicht feststellen, den Du erwähntest.

Viel Spass
Helge
Ich check das mal fix aus, Mega Dankeschön für Deine Mühe!
  Mit Zitat antworten Zitat
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
673 Beiträge
 
Delphi 10.4 Sydney
 
#19

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 17:09
Was ich nochmal erwähnen wollte zum Thema...

1. Es war so, wie ich sagt : nach dem SQL.Execute ist RecordCount bei 25, nach dem Assign auf der Zahl, was du wirklich an Register hast (Assign zieht alle register und dann kommt das natürlich hin). Der RecordCount der VT wird erst gesetzt, wenn sie offen ist (Active = True), sonst ist er 0.

Das im Thread ausführen bringt dir keinen Geschwindigkeitsvorteil, da das Query immer noch genauso langsam/schnell ist. Dazu müsstest Du die Daten stückeln, also in Blöcken anfordern. Wie ich vorher im Thread schonmal erwähnt hatte.

Helge
  Mit Zitat antworten Zitat
Benutzerbild von stOrM
stOrM

Registriert seit: 7. Jun 2003
Ort: Mülheim an der Ruhr
434 Beiträge
 
Delphi 10.3 Rio
 
#20

AW: SQL Query in Thread wie Datenrückgabe realisieren

  Alt 13. Okt 2016, 17:20
Jetzt wirds ganz lustig
Connection Name "Use Unicode" kennt er nicht. "CharacterSet" auch nicht. Wenn ich das raus nehme (ich denke mal liegt an der verschiedenen Version von Unidac die wir wohl haben) bekomm ich keine Daten
Macht aber erst mal nichts, ich werde das noch mal so umbauen mit meiner Version und dann mal schauen ob es dann geht, Ich denk mal Morgen bin ich damit soweit.

Alles klar funktioniert jetzt wunderbar. Nochmals vielen Dank für Deine Mühe!

Geändert von stOrM (13. Okt 2016 um 17:26 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:11 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