Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Multithreading (https://www.delphipraxis.net/121320-multithreading.html)

prelude247 25. Sep 2008 16:36


Multithreading
 
Hallo liebe DP'ler

ich bin dabei eine ältere Anwendung von mir, auf die neuen Multicore CPU's umzuschreiben.
Da ich aber noch nichts mit Thread zu tun hatte brauche ich etwas Hilfe.

Die besagte Anwendung generiert Daten und trägt diese dann in Datenbank ein. Jetzt habe ich angefangen
mit der Klasse TThread. Wie in einem Tutorial beschrieben hab ich die Klasse abgeleitet und die Methode Execute überschrieben.

Das ganze sieht dann so aus:

Delphi-Quellcode:
type
  meinThread = class(TThread)
  protected
    procedure Execute; override;
  end;
aufgerufen hab ich es dann wie folgt:

Delphi-Quellcode:
procedure bla();
var
  t1 : meinThread;
begin
  t1:=meinThread.Create(True);
  try
    t1.Execute;
  finally
    t1.Free;
  end;
end;
Nun hab ich mehrere Fragen zu der Geschichte:

Wie kann ich es realisieren mehrere Threads parallel laufen zu lassen?
Ist es sinnvoll die Threadanzahl der Anzahl an CPU's anzupassen?
Sollte ich in jedem Thread eine eigene Datenbankverbindung anlegen oder die eine auf der Mainform nutzen?

Ich danke allen Helfern schon mal im Voraus.

MfG
Prelude247

Für den Fall das es eine Rolle spielt, ich benutze die ZEOSlib und MySQL 5.

igel457 25. Sep 2008 16:42

Re: Multithreading
 
Dein Code...
Delphi-Quellcode:
  try
    t1.Execute;
  finally
    t1.Free;
  end;
...ist sinnlos. Überlege doch nochmal für was Threads überhaupt da sind - Richtig, um bestimmte Aufgaben parallel zur Hauptanwendung auszuführen. Was macht dein Code? Er startet einen Thread, der parallel zur Anwendung läuft. Nach dem Execute läuft also direkt deine Anwendung weiter und versucht den Thread freizugeben. Hierbei wird auf das Ende des Threads gewartet. Parallelität erreichst du so nicht. Und im schlimmsten Fall wird der Threadcontext freigegeben während er noch läuft. Das ist dann lustig.

prelude247 25. Sep 2008 16:53

Re: Multithreading
 
Danke für die rasendschnelle Antwort.

Ok, das mit dem freigeben ist wahrscheinlich Bödsinn (zumindest an dieser Stelle).

Jetzt habe ich aber versucht 4 von den Dingern laufen zulassen:

Delphi-Quellcode:
var
  t1,t2,t3,t4 : meinThread;
begin
  t1:=meinThread.Create(True);
  t2:=meinThread.Create(True);
  t3:=meinThread.Create(True);
  t4:=meinThread.Create(True);

  t1.Execute;
  t2.Execute;
  t3.Execute;
  t4.Execute;
end;
Aber die laufen nicht parallel, sondern werden nacheinander ausgeführt.
Was mache ich da falsch? Kann man das Erzeugen der Threads auch in einer Schleife machen?

NormanNG 25. Sep 2008 16:54

Re: Multithreading
 
Zitat:

Zitat von igel457
...Und im schlimmsten Fall wird der Threadcontext freigegeben während er noch läuft. Das ist dann lustig.

Thread-Execute wird im o.g. Fall wie eine "normale" Prozedur ausgeführt -
es passiert also kein "Freigeben während er noch läuft".

Du musste den Thread mit Resume starten. Dann wird automatisch die Execute-Prozedur (in einem eigenen Thread) ausgeführt.
Du solltest dabei beachten, dass dann natürlich der Thread nicht direkt freigegeben werden darf und das die
Execute-Prozedur auch irgendwann fertig wird. Für das erste Problem setze FreeOnTerminate auf True...

igel457 25. Sep 2008 16:59

Re: Multithreading
 
Zitat:

Zitat von NormanNG
Thread-Execute wird im o.g. Fall wie eine "normale" Prozedur ausgeführt -
es passiert also kein "Freigeben während er noch läuft".

Das würde ich so nicht unterschreiben - ich habe letztens eine Anwendung geschrieben, bei der ich auch von dieser Tatsache ausgegangen bin. In den meisten Fällen ist auch genau das passiert, was du beschrieben hast - ab und zu ist jedoch Anwendung mit einer Zugriffsverletzung abgestürzt.

Erst als ich in meinem Code noch ein "WaitFor" und ein "Terminate" eingeschoben hatte lief es ohne Probleme:
Delphi-Quellcode:
for i := 0 to High(Threads) do
begin
  Threads[i].Terminate;
  Threads[i].WaitFor;
  FreeAndNil(Threads[i]);
end;

sirius 25. Sep 2008 17:00

Re: Multithreading
 
Eine Datenbankanbindung pro Thread. Das geht aber nur, wenn es dein Konzept erlaubt, dass auch Datenbanksachen gleiczeitig laufen können. Ansonsten geht eben nur ein Datenbankthread.

Der Parameter im constructor gibt an, ob der Thread gleich loslaufen soll (False) oder noch auf ein Resume warten soll (True).
Und niemals Execute direkt aufrufen. Die Methode steht ja auch unter protected (und gehört besser unter strict protected).

littleDave 25. Sep 2008 17:01

Re: Multithreading
 
Hier mal ein kleines Beispiel:
(Benötigt 1 Formular mit einer TMemo und einer TButton-Komponente. Das "Button1Click" - Event gehört zu Button1: TButton;. Die Procedure "ThreadTerminated" musst du selbst in der Form deklarieren.

Delphi-Quellcode:
type
  TMyThread = class(TThread)
  protected
    Counter : integer; // nur für die Ausgabe
    procedure Execute; override;
  end;

procedure TMyThread.Execute;
begin
  // Der Thread soll einfach nur warten. Dabei wartet er
  // zufällig zwischen 1 und 11 Sekunden
  Sleep(1000 + random(10001));
end;

procedure TForm1.Button1Click(Sender: TObject);
var i: integer;
begin
  for i:=1 to 6 do
  begin
    Memo1.Lines.Add('Erstelle Thread Nummer '+IntToStr(i));
    with TMyThread.Create(True) do
    begin
      Counter        := i;
      FreeOnTerminate := True;
      OnTerminate    := ThreadTerminated;
      Resume;
    end;
  end;
end;

procedure TForm1.ThreadTerminated(Sender: TObject);
begin
  if Sender is TMyThread then
  begin
    Memo1.Lines.Add('Der Thread '+IntToStr(TMyThread(Sender).Counter)+' ist fertig');
  end;
end;
(Code ungetestet, da der ohne Delphi geschrieben wurde)

Bei dem Beispiel wirst du merken, dass das Programm trotz Sleep noch normal weiterläuft: es wird nur der Thread angehalten.


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