AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Datenbankabfragen mit Threads?

Ein Thema von hronny · begonnen am 18. Apr 2008 · letzter Beitrag vom 21. Apr 2008
Antwort Antwort
Seite 2 von 2     12   
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#11

Re: Datenbankabfragen mit Threads?

  Alt 20. Apr 2008, 13:11
Sybase kann definitiv mit mehreren Connections umgehen.
BTW hat den gleichen Ursprung wie der MSSQL-Server
Markus Kinzler
  Mit Zitat antworten Zitat
hronny

Registriert seit: 4. Mai 2006
Ort: Thüringen
97 Beiträge
 
Delphi 2007 Professional
 
#12

Re: Datenbankabfragen mit Threads?

  Alt 20. Apr 2008, 13:14
Damit sich irgendetwas während der Abfragen auf dem Formularfeld "bewegt". In dem Fall eine Uhr in der Statusleiste.

Es ist eine Embedded Variante die zusammen mit einer Software geliefert wird.
grep -ri shit /usr/src/linux/*
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#13

Re: Datenbankabfragen mit Threads?

  Alt 20. Apr 2008, 16:42
Solange obiger Quellcode keine Fehlermeldung verursacht vewendest du keine Threads, da:

1, Kein passendes Threading-Appartment für das COM-Subsystem angemeldet wird
2, Du keinerlei vorkehrungen hast die Connection (hier vor allem das COM-Interface) entsprechend für den Thread zu marshallen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#14

Re: Datenbankabfragen mit Threads?

  Alt 20. Apr 2008, 17:55
Zitat von hronny:
Und wie kann ich es dann machen? Da müsste quasi der Thread in einer Schleife sein und auf ein Signal warten?
Einfach so runtergetippt (und nur eine Möglichkeit ohne Sicherheiten):
Delphi-Quellcode:
interface

uses Classes, AdoDB, Windows, Messages, ActiveX;


const DM_Base=WM_User;
      DM_Ask=DM_Base+1;
      DM_Next=DM_Base+2;

      DM_Last=DM_Next;

type TSqlEvent=procedure(answer:integer) of object;

type
  TOpenQuery = Class(TThread)
  Public
    constructor Create(AConnectString:WideString; //as is
                       AonTerminate:TNotifyEvent; //wird ausgelöst, wenn Thread beendet oder abbricht
                       AOnSqlEvent:TSqlEvent); //wird ausgelöst, wenn neues Datenbankergebnis
    procedure Terminate; override; //Thread beenden
    function AskSQL(aSqlText:string):boolean; //neues SQL_Statement
    function NextSQL:boolean; //=SQLQuery.Next
  protected
    FQry: TADOQuery;
    FCon: TADOConnection;
    FSql: String;
    FConnectString: WideString;
    FOnSQLEvent:TSQLEvent;
    FAnswer:Integer;
    procedure Execute; override;
    procedure DoSQLCommand(var msg:TMessage); message DM_Ask;
    procedure DoSQLNext(var msg:TMessage); message DM_Next;

    procedure DoSQLEvent;
  end;

implementation

constructor TOpenQuery.Create();
begin
  inherited Create(False);
  FreeOnTerminate:=True;
  FConnectString:=aConnectString;
  onTerminate:=AonTerminate;
  FOnSQLEvent:=AOnSQLEvent;
end;

procedure TOpenQuery.Execute;
var msg:TMSG;
begin
  coinitialize(nil);
  FCon:=TAdoConnection.Create(nil);
  Fqry:=TAdoQuery.Create(nil);
  try
    FCon.ConnectionString:=FconnectString;
    Fqry.Connection:=FCon;
    FCon.Open;
    while not terminated and getmessage(msg,0,0,0) do
    begin
      if (msg.message>=DM_Base)and
         (msg.message<=DM_Last) then
        dispatch(msg) //Als message an die Klasse verteilen
      else
        dispatchmessage(msg); //Windows verteilen lassen
    end;
  finally
    Fqry.Free;
    FCon.Free;
    CoUninitialize;
  end;
end;
procedure TOpenQuery.Terminate;
begin
  inherited;
  PostThreadMessage(self.ThreadID,WM_quit,0,0); //getmessage abbrechen
end;
procedure TOpenQuery.DoSQLCommand(var msg:TMessage);
var sqltext:PString;
begin
  sqlText:=PString(msg.LParam);
  Fqry.active:=false;
  Fqry.SQL.Text:=sqlText^;
  dispose(sqlText);
  Fqry.Open;
  if not Fqry.eof then
  begin
    FAnswer:=Fqry.FieldByName('zahl').AsInteger;
    synchronize(DoSQLEvent);
  end; //else Maintthread informieren
end;
procedure TOpenQuery.DoSQLNext(var msg:TMessage);
begin
  if (Fqry.Active)and (not Fqry.Eof) then
  begin
    Fqry.Next;
    FAnswer:=Fqry.FieldByName('zahl').AsInteger;
    synchronize(DoSQLEvent);
  end;// else an MainThread melden
end;

procedure TOpenQuery.DoSQLEvent;
begin
  if assigned(FonSQLEvent) then
    FOnSQLevent(FAnswer);
end;

function TOpenquery.AskSQL(ASqlText:string):boolean;
var SQLText:PString;
begin
  new(SQLText);
  SQLTExt^:=ASqlText;
  result:=PostThreadMessage(self.ThreadID,DM_Ask,0,integer(SQLText));
  if not result then
    dispose(SQLTExt);
end;
function TOpenQuery.NextSQL;
begin
  result:=PostThreadMessage(self.ThreadID,DM_Next,0,0);
end;
Das soll mal ein Gerüst darstellen. Kommuniziert wird hier über Messages, was aber innerhalb der Klasse bleibt. Ich habe Messages gewählt, weil ich mir nicht sicher bin, ob das die ADO-Komponenten benötigen.
Auf jeden Fall muss man hier noch einige Sicherheiten einbauen. Insbesondere, da bei Auftreten eines Fehlers, der Thread einfach beendet wird und dein Mainthread das maximal über die onTerminate-Routine mitbekommt.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#15

Re: Datenbankabfragen mit Threads?

  Alt 20. Apr 2008, 17:59
Zitat von hronny:
Und wie kann ich es dann machen? Da müsste quasi der Thread in einer Schleife sein und auf ein Signal warten?
Einfach so runtergetippt (und nur eine Möglichkeit ohne Sicherheiten):
Delphi-Quellcode:
uses Classes, AdoDB, Windows, Messages, ActiveX;


const DM_Base=WM_User;
      DM_Ask=DM_Base+1;
      DM_Next=DM_Base+2;

      DM_Last=DM_Next;

type TSqlEvent=procedure(answer:integer) of object;

type
  TOpenQuery = Class(TThread)
  Public
    constructor Create(AConnectString:WideString; //as is
                       AonTerminate:TNotifyEvent; //wird ausgelöst, wenn Thread beendet oder abbricht
                       AOnSqlEvent:TSqlEvent); //wird ausgelöst, wenn neues Datenbankergebnis
    procedure Terminate; reintroduce; //Thread beenden
    function AskSQL(aSqlText:string):boolean; //neues SQL_Statement
    function NextSQL:boolean; //=SQLQuery.Next
  protected
    FQry: TADOQuery;
    FCon: TADOConnection;
    FSql: String;
    FConnectString: WideString;
    FOnSQLEvent:TSQLEvent;
    FAnswer:Integer;
    procedure Execute; override;
    procedure DoSQLCommand(var msg:TMessage); message DM_Ask;
    procedure DoSQLNext(var msg:TMessage); message DM_Next;

    procedure DoSQLEvent;
  end;

implementation

constructor TOpenQuery.Create;
begin
  inherited Create(False);
  FreeOnTerminate:=True;
  FConnectString:=aConnectString;
  onTerminate:=AonTerminate;
  FOnSQLEvent:=AOnSQLEvent;
end;

procedure TOpenQuery.Execute;
var msg:TMSG;
    VCLmsg:TMessage;
begin
  coinitialize(nil);
  FCon:=TAdoConnection.Create(nil);
  Fqry:=TAdoQuery.Create(nil);
  try
    FCon.ConnectionString:=FconnectString;
    Fqry.Connection:=FCon;
    FCon.Open;
    while not terminated and getmessage(msg,0,0,0) do
    begin
      if (msg.message>=DM_Base)and
         (msg.message<=DM_Last) then
      begin
        VCLmsg.Msg:=msg.message;
        VCLmsg.LParam:=msg.lParam;
        VCLmsg.WParam:=msg.wParam;
        VCLmsg.Result:=0;
        dispatch(VCLmsg) //Als message an die Klasse verteilen
      end else
        dispatchmessage(msg); //Windows verteilen lassen
    end;
  finally
    Fqry.Free;
    FCon.Free;
    CoUninitialize;
  end;
end;
procedure TOpenQuery.Terminate;
begin
  inherited;
  PostThreadMessage(self.ThreadID,WM_quit,0,0); //getmessage abbrechen
end;
procedure TOpenQuery.DoSQLCommand(var msg:TMessage);
var sqltext:PString;
begin
  sqlText:=PString(msg.LParam);
  Fqry.active:=false;
  Fqry.SQL.Text:=sqlText^;
  dispose(sqlText);
  Fqry.Open;
  if not Fqry.eof then
  begin
    FAnswer:=Fqry.FieldByName('zahl').AsInteger;
    synchronize(DoSQLEvent);
  end; //else Maintthread informieren
end;
procedure TOpenQuery.DoSQLNext(var msg:TMessage);
begin
  if (Fqry.Active)and (not Fqry.Eof) then
  begin
    Fqry.Next;
    FAnswer:=Fqry.FieldByName('zahl').AsInteger;
    synchronize(DoSQLEvent);
  end;// else an MainThread melden
end;

procedure TOpenQuery.DoSQLEvent;
begin
  if assigned(FonSQLEvent) then
    FOnSQLevent(FAnswer);
end;

function TOpenquery.AskSQL(ASqlText:string):boolean;
var SQLText:PString;
begin
  new(SQLText);
  SQLTExt^:=ASqlText;
  result:=PostThreadMessage(self.ThreadID,DM_Ask,0,integer(SQLText));
  if not result then
    dispose(SQLTExt);
end;
function TOpenQuery.NextSQL;
begin
  result:=PostThreadMessage(self.ThreadID,DM_Next,0,0);
end;
Das soll mal ein Gerüst darstellen. Kommuniziert wird hier über Messages, was aber innerhalb der Klasse bleibt. Ich habe Messages gewählt, weil ich mir nicht sicher bin, ob das die ADO-Komponenten benötigen.
Auf jeden Fall muss man hier noch einige Sicherheiten einbauen. Insbesondere, da bei Auftreten eines Fehlers, der Thread einfach beendet wird und dein Mainthread das maximal über die onTerminate-Routine mitbekommt.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
hronny

Registriert seit: 4. Mai 2006
Ort: Thüringen
97 Beiträge
 
Delphi 2007 Professional
 
#16

Re: Datenbankabfragen mit Threads?

  Alt 20. Apr 2008, 22:03
Danke erstmal für die aufwändige Antwort. Es erscheint mir sehr kompliziert, das muss ich in Ruhe durchprobieren. Dachte echt das geht einfacher. Ich brauch keine Multiabfragen, sondern einfach nur eine Datenbankabfrage nach der nächsten. Solange wie eine Abfrage läuft, soll sich in meinem Hauptformular irgendetwas bewegen (in dem Fall soll die Uhr weiter laufen). Nach der Abfrage möchte ich von meinem Hauptformular die Daten weiterverarbeiten. Vielleicht bekomme ich es mit dem oben genannten Ansatz hin, wobei ich in Threads noch absoluter Greenhorn bin.
grep -ri shit /usr/src/linux/*
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#17

Re: Datenbankabfragen mit Threads?

  Alt 20. Apr 2008, 22:13
ADO (oder wars nur der MS SQL Server über ADO) kann die Ergebnisdatenmenge (wenn sie z.B. in einem Grid benötigt wird) asynchron zurückliefern. Ob das auch der Provider von Sybase kann weis ich nicht.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#18

Re: Datenbankabfragen mit Threads?

  Alt 21. Apr 2008, 06:10
Also wenn ich eine Abfrage hätte, die 15 Sekunden dauert, dann würde ich mal an dieser Abfrage rumfeilen. Optimiert ist das 100% *nicht*, denn mit dem Einsatz (redundanter) Zwischenergebnisse (z.B. Monatssummen o.ä.) würde man das in ein paar ms hinbekommen. Und falls die 15 Sek dafür benötigt werden, Hunderttausende von Datensätzen in die Applikation tu schaufeln, ist das auch nicht der richtige Weg.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


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 20:42 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