AGB  ·  Datenschutz  ·  Impressum  







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

Thread für einfache Funktionsauslagerungen

Ein Thema von ibp · begonnen am 20. Jun 2012 · letzter Beitrag vom 20. Jun 2012
Antwort Antwort
Benutzerbild von ibp
ibp

Registriert seit: 31. Mär 2004
Ort: Frankfurt am Main
1.511 Beiträge
 
Delphi 7 Architect
 
#1

Thread für einfache Funktionsauslagerungen

  Alt 20. Jun 2012, 11:20
Hallo,

beim Umstellen eines Programms von Methoden auf Stored Procedures soll das ganze in einen Thread gepackt werden. Die SP sind komplex und zeitaufwendig, bisher wurden diese von der Mainform übernommen. Dabei gab es dann ein Infofenster mit einer Pseudoprogressbar die signalisiert das etwas in Arbeit ist. Bei der Umstellung auf SP friert nun dieses Infofenster ein. Lösung: Auslagerung in Thread.

Ist der nachfolgende Ansatz so richtig oder was ist noch zu beachten. Geht er vielleicht einfacher?

Danke schon mal....

Delphi-Quellcode:
  TMachWasLangesInDerDBThread = class(TThread)
    private
      fSPQuery : TIBQuery;
      fInProgress : Boolean;
    protected
      procedure Execute(); override;
    public
      constructor create(const aPKey,aTKey:TKey; aChildLevel:Integer);
      destructor Destroy; override;

      property InProgress : Boolean read fInProgress;
  end;

constructor TMachWasLangesInDerDBThread.create(const aPKey,aTKey:TKey; aChildLevel:Integer);
begin
  inherited create(False);
  FreeOnTerminate := False;

  fInProgress := True;

  fSPQuery := TIBQuery.Create(nil);
  try
    fSPQuery.SQL.Text:='EXECUTE PROCEDURE P_SORT...';
    fSPQuery.ParamByName(...);
  except
    on e: exception do
    begin
      showmessage(e.Message);
    end;
  end;
end;

destructor TMachWasLangesInDerDBThread.Destroy;
begin
  if Assigned(fSPQuery) then
  begin
    fSPQuery.Free;
  end;

  inherited destroy;
end;

procedure TMachWasLangesInDerDBThread.Execute;
begin
  try
    fSPQuery.ExecSQL;
  except
    on e: exception do
    begin
      showmessage(e.Message);
    end;
  end;
  fInProgress := False;
end;

.... im Hauptprozess Aufruf durch...

...
MeinInfoFenster.show;

aMYThread := TMachWasLangesInDerDBThread.create(...);
try
  while aMYThread.InProgress do
  begin
    MeinInfoFenster.Action;
    Sleep(1000);
  end;
finally
  aMYThread.Free;
end;
...

Geändert von ibp (20. Jun 2012 um 11:23 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

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

AW: Thread für einfache Funktionsauslagerungen

  Alt 20. Jun 2012, 11:22
Ist die verwendete DB-Komponente Thread-Save?
D.h. darfst du von unterschiedlichen Query-Komponenten auf eine einzige Connection-KOmponente zugreifen?
Falls nicht musst du in jedem Thread eine eigene DB-Verbindung aufbauen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von ibp
ibp

Registriert seit: 31. Mär 2004
Ort: Frankfurt am Main
1.511 Beiträge
 
Delphi 7 Architect
 
#3

AW: Thread für einfache Funktionsauslagerungen

  Alt 20. Jun 2012, 11:30
das wäre nicht das Problem, ich kann ja die Entsprechenden Infos aus dem Hauptthread übergeben.

Was mir mehr sorgen macht, ist...
Delphi-Quellcode:
while aMYThread.InProgress do
begin
  MeinInfoFenster.Action;
  Sleep(1000);
end;
was ist wenn das durch ein Fehler zu einer Endlosschleife wird? Wie kann ich das vielleicht anders lösen?
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Thread für einfache Funktionsauslagerungen

  Alt 20. Jun 2012, 11:54
Wie wäre es ohne sleep aber mit Triggerung durch einen Timer?
oder so:
Delphi-Quellcode:
while aMYThread.InProgress do
begin
  aMyThread.InProgres:=false; {ich hab das read gesehen.....}
  MeinInfoFenster.Action;
  Sleep(1000);
end;
Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
678 Beiträge
 
FreePascal / Lazarus
 
#5

AW: Thread für einfache Funktionsauslagerungen

  Alt 20. Jun 2012, 12:02
Warum kann Sleep nicht endlich aus der RTL rausgeworfen werden?

Deutlich besser ist WaitForSingleObject, dann lässt sich die "Wartepause" auch abbrechen (sonst z.B. nervig wenn bei Programmende einige Threads noch die eine oder andere Sekunde schlafen, beim System runterfahren, wenn man einfach nur abbrechen will...). Zum Beispiel mit einem Event (auf den man damit wartet).

Geändert von CCRDude (20. Jun 2012 um 12:06 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

AW: Thread für einfache Funktionsauslagerungen

  Alt 20. Jun 2012, 12:12
Wird das Query wirklich im Thread ausgeführt. Denn wenn die Komponente in TThread.create erstellt wird, gehört sie zumindest noch dem Mainthread (müsste man überprüfen, wie die Komponente arbeitet.

Ansonsten: sleep vermeiden, steht ja schon da.


Edit:
Ich persönlich find es blöd, da die Hauptanwendung im Endeffekt wieder einfriert.
Sieht ja so aus, als ob das notwendig ist. Stichwort Splashscreen und Vorarbeiten beim Start.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
NickelM

Registriert seit: 22. Jul 2007
Ort: Carlsberg
445 Beiträge
 
Delphi 2009 Professional
 
#7

AW: Thread für einfache Funktionsauslagerungen

  Alt 20. Jun 2012, 12:10
Lass das mit Sleep und so weg, und mach eine Synchronize-Funktion am Ende das Thread, wo du fInProgress := False; hast. Damit sind beide Threads (Haupthread, also dein Fenster, und dein "Arbeiterthread") unabhängig von einander. Das mit ShowMessage im except würd ih ändern. Dass könnte unter umständen mal knallen. Verwende lieber MessageBox von Windows. Ist sicherer und bietet mehr

Nachtrag, wegen anderen Posts : Oder mit WaitForSingleObject, wie schon erwähnt . Ich persönlich find es blöd, da die Hauptanwendung im Endeffekt wieder einfriert.

Gruß NickelM
Nickel
"Lebe und denke nicht an morgen"
Zitat aus dem gleichnamigen Bollywoodfilm.
  Mit Zitat antworten Zitat
NickelM

Registriert seit: 22. Jul 2007
Ort: Carlsberg
445 Beiträge
 
Delphi 2009 Professional
 
#8

AW: Thread für einfache Funktionsauslagerungen

  Alt 20. Jun 2012, 17:22
@ChrisE : Er meinte, wie ich das mit meinem Post bezüglich Synchronize meinte.
@ibp : Okay hab mich zugegeben bischen doff ausgedrückt. Ich meinte, dass du das alles ein bischen anders aufbauen kannst, und somit kein Sleep oder sonstiges mehr brauchst.

Delphi-Quellcode:
  
TMachWasLangesInDerDBThread = class(TThread)
    private
      ...
      FErrorMsg : String; //Da man keine Funktion mit Parameter synchronizieren kann
      procedure OnErrorDo;
      procedure OnFinishDo;
    protected
      procedure Execute; override;
    public
   ...
  end;

procedure TMachWasLangesInDerDBThread.Execute;
begin
  try
    fSPQuery.ExecSQL;
  except
    on e: exception do
    begin
      FErrorMsg := e.Message;
      Synchronize(OnErrorDo);
      Terminate; //Zur Sicherheit
    end;
  end;
  Synchronize(OnFinishDo);
  Terminate; //Zur Sicherheit
end;

procedure TMachWasLangesInDerDBThread.OnErrorDo;
begin
  ShowMessage(FErrorMsg);
  //OnFinishDo; oder was du beim Error sonst nach alles gemacht hättest.
end;

procedure TMachWasLangesInDerDBThread.OnFinishDo;
begin
  //z.b. MeinInfoFenster.hide; oder was du nach deiner Schleife gemacht hättest
end;

.... im Hauptprozess Aufruf durch...

...
MeinInfoFenster.show;
aMYThread := TMachWasLangesInDerDBThread.create(...);
aMYThread.FreeOnTerminate := True;
So habe ich dass immer gelöst, wenn ich auf einen Thread warten musste. Damit bleibt das Fenster, wenn überhaupt, nur beim Synchronize-Teil kurz hängen, da beide Thread ja zusammen arbeiten.

Gruß NickelM
Nickel
"Lebe und denke nicht an morgen"
Zitat aus dem gleichnamigen Bollywoodfilm.
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#9

AW: Thread für einfache Funktionsauslagerungen

  Alt 20. Jun 2012, 18:48
Ich verwende einen Connectionpool, der mir TIBDatabase-Componenten bereit hält.

Die Threads haben eine lokale im Thread erzeugte TIBStoredProc-Instanz. Beim Ausführen fordern sie eine Connection an, weisen sie der SP zu, führen sie aus und geben die Connection wieder an den Pool zurück.

Der Pool verwaltet nur eine TThreadList if TIBDatabase. Wenn eine Verbindung angefordert wird, aber die Liste leer ist, wird eine neue erstellt.

Keine Ahnung, ob das sinnig ist, aber ich habe es mal so umgesetzt und das läuft sehr gut. Ich verwende das für eine Datenpumpe, wobei die Threads als Workerthread fungieren.

Ich würde außerdem zusehen, das die SP nicht allzulange braucht. Wenn sie das tut, hast Du vermutlich etwas falsch gemacht.
  Mit Zitat antworten Zitat
Antwort Antwort


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 18:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz