Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Tutorials und Kurse (https://www.delphipraxis.net/36-tutorials-und-kurse/)
-   -   Delphi einfaches Multithread Beispiel. (https://www.delphipraxis.net/203981-delphi-einfaches-multithread-beispiel.html)

gemy 12. Apr 2020 20:46


Delphi einfaches Multithread Beispiel.
 
Hier ein einfaches Multithread Beispiel ohne viel Schnörkel:

Beschreibung: Es wird Speicher reserviert für 20 Threads. 20 Threads werden gestartet über ein array of TmyThread. Gestartete Threads schreiben in ein Memo ihre Thread ID. Die Threads zählen ein integer hoch in Form1.caption. Je mehr threads gestartet desto schneller.

Wird ein Thread geschlossen, so entfernt er seine Thread ID aus dem Memo. Über den zweiten Button können alle Threads über eine Schleife gleichzeitig beendet werden.

Wer Verbesserungsvorschläge hat kann diese natürlich hinzufügen :thumb:

Es werden benötigt: 2 Buttons und 1 Memo.

--Die aktuelle korrigierte Version findet sich weiter unten--

Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Comctrls, System.ImageList,
  Vcl.ImgList, Vcl.StdCtrls;

type
  TmyThread = class(TThread)
    procedure Execute; override;
    procedure Synthreads;
    procedure Syni;
  end;
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }

  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  i:integer =0;
  var threads: array of cardinal;
  var meinThread: array of TmyThread;
implementation

{$R *.dfm}



procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
SetLength(meinthread, 20);
for i := 0 to high(meinThread) do
meinThread[i]:= TmyThread.Create(false);
end;

{ TmyThread }

procedure TmyThread.Execute;
var z: integer;
var cnt: integer;

begin
  inherited;
  SetLength(threads, length(threads)+1);
  threads[(high(threads))] := self.ThreadID;
  SYNCHRONIZE(Self.Synthreads);
  for z := 0 to 50 do
  begin
    inc(i);
    sleep(random(500));
    Synchronize(Syni);
    if Terminated then break;

  end;
  for cnt:= low(threads) to High(threads) do
  if threads[cnt] = self.ThreadID then
   begin
      threads[cnt] := threads[high(threads)];
      SetLength(threads, length(threads)-1);
   end;
  Synchronize(Synthreads);
end;




procedure TmyThread.Syni;
begin
form1.Caption:= inttostr(i);
end;

procedure TmyThread.Synthreads;
var line: integer;
begin
form1.memo1.clear;
for line := Low(threads) to High(threads) do
form1.Memo1.Lines.Add(inttostr(threads[line]));

end;

procedure TForm1.Button2Click(Sender: TObject);
var i:integer;
begin
if Length(meinThread) >0  then
for I := 0 to high(meinThread) do
if ((meinThread[i] <> nil ) and (meinThread[i].Terminated = false)) then meinThread[i].Terminate;
end;


end.

DieDolly 12. Apr 2020 20:57

AW: Delphi einfaches Multithread Beispiel.
 
Ich bin kein MuiThreading-Profi aber ich finde das hier solltest du nicht als Beispiel posten.
Ich würde es grundlegend anders machen und Synchronize komplett rausschmeißen. Sendmessage/Postmessage und dann abarbeiten.
Dann würde ich auch niemals einen Thread mit Terminate beenden. Eher Events oder so. Und dann dieser Vergleich auf False.
Von globalen Variablen fange ich gar nicht erst an.

Ich werde jetzt sicher wieder von allen Seiten angemacht, weil ich nur am meckern bin. Aber das ist kein guter Beispielcode.

Redeemer 12. Apr 2020 21:28

AW: Delphi einfaches Multithread Beispiel.
 
Die Nutzung von globalen Variablen wird nicht gern gesehen. Es gibt keinen Grund, die nicht zumindest in den Implementationsabschnitt zu verfrachten. Außerdem ist hier das falsche Schlüsselwort var verwendet, wobei threadvar keine automatische Speicherverwaltung auch nicht für nicht-primitive Nicht-Klassen hat. Und die Namen der Variablen überschneiden sich. Man würde allgemein keine Variable i nennen, die keine lokale Zählvariable ist.

jfheins 12. Apr 2020 21:33

AW: Delphi einfaches Multithread Beispiel.
 
Guten Abend :-)
Zitat:

Ich werde jetzt sicher wieder von allen Seiten angemacht, weil ich nur am meckern bin. Aber das ist kein guter Beispielcode.
Zum Teil, aber zum Teil hast du mMn auch zu wenig kritisiert :twisted:

Zitat:

Zitat von DieDolly (Beitrag 1461880)
Ich würde es grundlegend anders machen und Synchronize komplett rausschmeißen. Sendmessage/Postmessage und dann abarbeiten.

Also ich finde, Synchronize ist für ein kleines Beispiel schon OK. SendMessage/Postmessage wäre für mich schon eher fortgeschritten, weil die Datenübergabe komplexer ist.
Zitat:

Dann würde ich auch niemals einen Thread mit Terminate beenden.
Das finde ich schon i.O., weil das ja nur das Terminated flag setzt. Völlig harmlos, der Thread fragt das Flag ab und beendet sich bei Gelegenheit. Hat nichts mit dem WINAPI TerminateThread() zu tun.

Aber jetzt zum interessanten Teil - ich habe mal kommentiert:
Delphi-Quellcode:
procedure TmyThread.Execute;
var
  z: integer;
  cnt: integer;
begin
  inherited; // Unnötig
  SetLength(threads, length(threads)+1); // Gefährlich - SetLength ist NICHT thread-safe!
  threads[(high(threads))] := self.ThreadID;
  SYNCHRONIZE(Self.Synthreads);
  for z := 0 to 50 do
  begin
    inc(i); // Integer-zugriff ist atomar und damit i.O. (soweit ich weiß)
    sleep(random(500));
    Synchronize(Syni);
    if Terminated then
     break;
  end;
  for cnt:= low(threads) to High(threads) do
  if threads[cnt] = self.ThreadID then
   begin
      threads[cnt] := threads[high(threads)];
      SetLength(threads, length(threads)-1); // Auch hier eine race condition, mehrere Thread könnten SetLength gleichzeitig aufrufen!
     // Außerdem ein Speicherleck, der Thread wird nicht freigegeben
   end;
  Synchronize(Synthreads);
end;


procedure TForm1.Button2Click(Sender: TObject);
var i:integer;
begin
if Length(meinThread) >0  then // Überflüssig, die Schleife läuft ohne Elemente eh nicht
  for I := 0 to high(meinThread) do
    // Vergleich auf nil _aktuell_ überflüssig, da du es nie auf nil setzt. Zudem auch der check auf Terminated überflüssig - zweimal aufrufen schadet nicht.
    if ((meinThread[i] <> nil ) and (meinThread[i].Terminated = false)) then
     meinThread[i].Terminate;
end;

gemy 13. Apr 2020 09:37

AW: Delphi einfaches Multithread Beispiel.
 
Guten Morgen!


Habe alles nochmal überarbeitet. Setlength rausgeworfen und die Thread id mit in das array gepackt. Wenn der Thread durchgelaufen ist, wird die ID auf 0 gesetzt, und erscheint dann auch im memo nicht mehr.

Kritik erwünscht !

Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Comctrls, System.ImageList,
  Vcl.ImgList, Vcl.StdCtrls;

type
  TmyThread = class(TThread)
    private
      fmeineThreadID: cardinal;
    public
    procedure Execute; override;
    procedure Synthreads;
    procedure Syni;
    property meineThreadID: Cardinal Read fmeineThreadID Write fmeineThreadID;
  end;
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }

  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  i:integer =0;
  var meinThread: array of TmyThread;
implementation

{$R *.dfm}



procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
SetLength(meinthread, 20);
for i := 0 to high(meinThread) do
   meinThread[i]:= TmyThread.Create(false);
end;

{ TmyThread }

procedure TmyThread.Execute;
var z: integer;
begin
  fmeineThreadID := ThreadID;
  SYNCHRONIZE(Self.Synthreads);
  for z := 0 to 50 do
  begin
    inc(i);
    sleep(random(500));
    Synchronize(Syni);
    if Terminated then break;
  end;
  fmeineThreadID:= 0;
  Synchronize(Synthreads);
  FreeOnTerminate := true;
end;




procedure TmyThread.Syni;
begin
form1.Caption:= inttostr(i);
end;

procedure TmyThread.Synthreads;
var line: integer;
begin
form1.memo1.clear;
for line := Low(meinThread) to High(meinThread) do
if meinThread[line].meineThreadID <> 0 then form1.Memo1.Lines.Add(inttostr(meinThread[line].ThreadID));
end;

procedure TForm1.Button2Click(Sender: TObject);
var i:integer;
begin
for I := 0 to high(meinThread) do
if ((meinThread[i] <> nil ) and (meinThread[i].Terminated = false)) then meinThread[i].Terminate;
end;


end.

p80286 13. Apr 2020 09:43

AW: Delphi einfaches Multithread Beispiel.
 
Natürlich darf man Synchronize verwenden. Das ist dann wie ein Chef der die ganze Zeit über die Schulter schaut und sich dann beschwert, daß er sich um alles kümmern muß.Ein Thread ist erst dann sinnvoll wenn er "autark gedacht" wird. Wenn er länger läuft darf er messages versenden die dann vom Mainthread ausgewertet werden, das war es aber auch schon. Ist nicht ganz simpel aber machbar.

Gruß
K-H

Mavarik 13. Apr 2020 09:52

AW: Delphi einfaches Multithread Beispiel.
 
Oje...

Ich werde keine Kritik schreiben - es ist noch kein Meister von Himmel gefallen...

Delphi-Quellcode:
for var i:=0 to 19 do
  TTask.Run()
Daher: Meine CodeRage2020 Session: Threads & Queues...

Gausi 13. Apr 2020 10:14

AW: Delphi einfaches Multithread Beispiel.
 
Frage dazu, weil ich es nicht sicher weiß, aber sehr stark "nein" vermute:

Darf man auf eine globale Integer-Variable (hier: i) von mehreren Threads aus einfach so per inc(i) zugreifen? Ist Inc wirklich atomar, oder müsste das nicht auch abgesichert werden (InterlockedIncrement, AtomicIncrement, CriticalSection, whatever?)

himitsu 13. Apr 2020 11:40

AW: Delphi einfaches Multithread Beispiel.
 
Ja, Nein, ist es nicht. :stupid:

Delphi-Quellcode:
INC x
im Assembler ist nicht thread-safe, allerdings
Delphi-Quellcode:
LOCK INC x
ist es,
aber niemand will nur deswegen mit Assembler rumpfuschen, darum
https://www.delphipraxis.net/203952-...ml#post1461765
Die Lesezugriffe, ohne zusätzliche Absicherung, sind es damit dann auch.
Falls man den Wert aber mehrmals (z.B. der IF dann nochmal) verwenden will, dann sollte man sich den Wert einmal kopieren (nur ein Zugriff und dann unveränderliche Kopie).

DieDolly 13. Apr 2020 12:33

AW: Delphi einfaches Multithread Beispiel.
 
Eigentlich müsste man den kompletten Code streichen und ersetzen. Kein Anfänger oder überhaupt jemand sollte sich ein beispiel daran nehmen.

Ich empfehle hier zumindestest https://de.wikibooks.org/wiki/Progra...ascal:_Threads

p80286 13. Apr 2020 13:02

AW: Delphi einfaches Multithread Beispiel.
 
Zitat:

Zitat von himitsu (Beitrag 1461923)
Ja, Nein, ist es nicht. :stupid:

Delphi-Quellcode:
INC x
im Assembler ist nicht thread-safe, allerdings
Delphi-Quellcode:
LOCK INC x
ist es,
aber niemand will nur deswegen niemand mit Assembler rumpfuschen,

Man lernt nie aus. Ich hielt das bisher für threadsafe - Glück gehabt.
Zeigt nur das der oft gebrauchte Rat "versuch es ..." nicht immer gut ist.

Gruß
K-H

Uwe Raabe 13. Apr 2020 13:37

AW: Delphi einfaches Multithread Beispiel.
 
Multi-Threading ist in dieser Hinsicht um ein Vielfaches böswilliger als nicht initialisierte Variablen. Es wiegt dich teilweise über mehrere Jahre in Sicherheit und schlägt dann ganz unvermittelt aber erbarmungslos zu. Weil die relevante Code-Änderung dummerweise schon so lange zurückliegt, ist das oft ganz schwer herauszufinden.

Redeemer 13. Apr 2020 16:27

AW: Delphi einfaches Multithread Beispiel.
 
Zitat:

Zitat von Gausi (Beitrag 1461914)
Frage dazu, weil ich es nicht sicher weiß, aber sehr stark "nein" vermute:

Darf man auf eine globale Integer-Variable (hier: i) von mehreren Threads aus einfach so per inc(i) zugreifen? Ist Inc wirklich atomar, oder müsste das nicht auch abgesichert werden (InterlockedIncrement, AtomicIncrement, CriticalSection, whatever?)

Für Details empfehle ich dieses Video (Zeitstempel beachten) von Bernd Ua von der CodeRage 2019, wo er genau das anschaulich zeigt.

Gausi 13. Apr 2020 18:01

AW: Delphi einfaches Multithread Beispiel.
 
Gut, dann lag ich ja richtig.

@Redeemer: danke für den Link. Schau ich mir bei Gelegenheit mal genauer an! :thumb:

gemy 13. Apr 2020 18:15

AW: Delphi einfaches Multithread Beispiel.
 
habe mir nun https://www.youtube.com/watch?v=WOc89TF8l-8 angesehen.

Wie kann ich den thread löschen ?

himitsu 13. Apr 2020 18:26

AW: Delphi einfaches Multithread Beispiel.
 
@p80286

Ja, es ist schon recht schwer zwei Threads fast zur selben Zeit auf die selbe Speicheradresse zugreifen zu lassen, womit es auch schonmal jahrelang gut gehn "kann",
vor allem da in Delphi standardmäßig alle Variablen absichtlich gut ausgerichtet sind.

OK, im Prnzip hat der RAM "grundsätzlich" nur Adressleitung, womit es unmöglich wäre genau gleichtzeitig zuzugreifen,
aber fangen DualChanel an (zwei Adressleitungen) oder DoubleDataRate (DDR) wo zwei Zugriffe auf einer Leidung liegen (einer bei steigender Flanke und der andere bei Fallender) ..........

Und wenn wir es uns jetzt noch einfach machen und annehmen, dass Speicherzugriffe immer genau auf 4 Byte ausgerichtet sind
und du einen Integer zwischen zwei Zugriffspunkten positionierst, dann sind es zwei einzelne Zugriffe, die dann noch entsprechen maskiert, verschoben und kombiniert werden.
Zitat:

#### #### #### #### #### RAM
x xxx unser Integer
Hier wird dann der erste Integer gelesen aus dem RAM gelesen, das letzte Byte genommen und nach links verschoben, danach dann noch er zweite Integer um ein Byte nach rechts und alles ORen.

Hier ist die Chance gleich ein Vielfaches höher, das Threads sich dabei überschbeiden.

> Wert aus RAM in Register kopieren > hochrechnen > und den Wert wieder zurück in den RAM kopieren

Dafür gibt es das LOCK, wo dann ein Speicherbereich für andere Kerne gesperrt wird.




Bei MultiThread mit mehreren Kernen mag das noch einfach sein, sowas innerhalb eines Chips/Prozessors zu behandeln.
PS: Vergesst nicht, dass früher auch nicht alles in der CPU drin war, sondern alles einzelne Funktionseinheiten/Chips die sich dann noch unterhalten müssten. (in Smartphons, Tablets, Schlepptops und vor allem MiniPCs sind CPU, FPU, NorthBridge, SouthBridge, GPIO, Speichercontroller, ... oft nur noch Eins)

Aber schlimmer wird es dann auch noch bei MultiCPU, also mehrere Kerne in mehreren Chips auf vielleicht auch noch mehreren verbundenen Boards.
Oder ganz modern, verteilte Rechenleitung über mehreren Rechenzentren.

In guten Cloudlösungen kannst Problemlos dein Programm in China laufen lassen und es mittendrin und ohne Unterbrechung nach Russland verschieben, in ein anderes Rechenzentrum deines Anbieters.

himitsu 13. Apr 2020 18:29

AW: Delphi einfaches Multithread Beispiel.
 
Task = Thread+
Vielleicht besser erstmal klein anfangen, also direkt Threads.

Mit Tasks (Fiber im Windows-Jargon) wird es noch spaßiger,
da es Arbeitseinheiten sind, die wiederum in einem/mehreren Threads verarbeitet werden.

Man könnte Tasks sogar im Hauptthread ausführen lassen, womit es in der Programmierung wie MultiThread aussähe, aber eigentlich SingleThread wäre. :stupid:

p80286 13. Apr 2020 18:54

AW: Delphi einfaches Multithread Beispiel.
 
@himitsu
Ich hab meine ersten Parallelschritte auf einer Einschubkarte mit T800 gemacht. Da war unser liebstes Wort "Deadlock" der hatte ein Speicherschutzkonzept das einen Anfänger in den Wahnsinn treiben konnte. Einziger Vorteil: du hast gelernt dich zu beschränken. Ich hab nur geflucht nd die Karte nach einem halben Jahr versenkt. Heute zehre ih immer noch von den damaligen Erfahrungen.....

Gruß
K-H

Redeemer 13. Apr 2020 20:07

AW: Delphi einfaches Multithread Beispiel.
 
Zitat:

Zitat von gemy (Beitrag 1461948)
habe mir nun https://www.youtube.com/watch?v=WOc89TF8l-8 angesehen.

Wie kann ich den thread löschen ?

Thread löschen ist immer blöd, so können andere den hier gegangenen Gedankengang nicht nachvollziehen. Verschieben wäre besser.

Sherlock 14. Apr 2020 07:41

AW: Delphi einfaches Multithread Beispiel.
 
Den Thread würde ich nicht löschen wollen. Ich empfinde ihn als gutes Tutorial, wie man hier gemeinsam zu der Lösung eines Problems kommen könnte, nebst sinnvoller Nebenschauplätze.

Sherlock

Luckie 14. Apr 2020 18:49

AW: Delphi einfaches Multithread Beispiel.
 
Ich meine, ich habe in meinem Threadtutorial zwei einfache Beispiele. Eins für die WinAPI und eins für die VCL. Nebenbei kann man damit auch etwas tiefer in die Materie einsteigen.

p80286 14. Apr 2020 20:46

AW: Delphi einfaches Multithread Beispiel.
 
Delphi-Quellcode:
procedure TmyThread.Syni;
begin
form1.Caption:= inttostr(i);
end;

procedure TmyThread.Synthreads;
var line: integer;
begin
form1.memo1.clear;
for line := Low(threads) to High(threads) do
form1.Memo1.Lines.Add(inttostr(threads[line]));
end;
Du setzt zwingend vorraus, das es ein Form1 gibt. Das ist mindestens leichtsinnig. Falls Du auf eine variable ausserhalb Deines Objektes zugreifen willst solltest Du diese auch offensichtlich übergeben.


Delphi-Quellcode:
if ((meinThread[i] <> nil ) and (meinThread[i].Terminated = false)) then meinThread[i].Terminate;
Du bist schon weiter oben darauf hingewiesen worden, daß dies eher suboptimal ist.

Gruß
K-H

Luckie 14. Apr 2020 21:00

AW: Delphi einfaches Multithread Beispiel.
 
Link vergessen: http://michael-puff.de/Programmierung/Delphi/Tutorials/

himitsu 14. Apr 2020 21:22

AW: Delphi einfaches Multithread Beispiel.
 
Jo, auch für die Wiederverwendbarkeit vorn Code ist es ungut hier "global" auf Form1 zuzugreifen,
sondern man könnte hier ein TMemo (Memo1) oder besser noch TStrings (Memo1.Lines) reingeben, denn dem kann man auch antere StringListen als Log reingeben.
Aber am Besten ist hier ein CallBack zuräck in die Form, wo die Form oder sonstwer dann mit dem LogText machen kann, was er will, ohne dass man an ein TMemo auf einer Form1 gebunden ist.


Zitat:

Zitat von p80286 (Beitrag 1462049)
Delphi-Quellcode:
if ((meinThread[i] <> nil ) and (meinThread[i].Terminated = false)) then meinThread[i].Terminate;

Delphi-Quellcode:
if ... = False then

Wer möchte dafür mit einem rosa Wattebausch gesteinigt werden?

Und ratet mal was Terminate macht?
Genau, es setzt nur Terminated auf True, also unnötig das nochmal zu prüfen, denn TRUEr als TRUE kann es nicht werden.

Delphi-Quellcode:
if Assigned(meinThread[i]) then
  meinThread[i].Terminate;
Und schon ist die Zeile extrem übersichtlich.

gemy 18. Apr 2020 15:15

AW: Delphi einfaches Multithread Beispiel.
 
Guten Abend zusammen. Habe alles nochmal überarbeitet.
Hier das Ergebniss. Erhöhe jetzt i mit atomic increment. Synchronize durch queue ersetzt. Habe von https://www.youtube.com/watch?v=WOc89TF8l-8&t=648s viel gelernt.


Kritik erwünscht und Verbesserungsvorschläge !


Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Comctrls, System.ImageList,
  Vcl.ImgList, Vcl.StdCtrls;

type
  TmyThread = class(TThread)
    private
      FMainThreadLog: TStrings;
    public
    constructor Create(Alog: Tstrings; DoOnTerminate: TnotifyEvent);
    procedure Execute; override;
    procedure OutputMessage(const Amessage: string);
  end;
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure HandleTerminate(Sender: Tobject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }

  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  i:integer =0;

implementation

{$R *.dfm}



procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
for i :=0 to 5 do TmyThread.Create(ListBox1.Items, HandleTerminate);
end;





{ TmyThread }

constructor TmyThread.Create(Alog: Tstrings; DoOnTerminate: TnotifyEvent);
begin
inherited Create(false);
FMainThreadLog := Alog;
FreeOnTerminate := true;
OnTerminate := DoOnterminate;
end;

procedure TmyThread.Execute;
var z: integer;
begin
  TmyThread.Queue(nil, procedure
                        begin
                          FMainThreadLog.Add(IntToStr(ThreadID));
                        end
                        );
  for z := 0 to 49 do
  begin
    AtomicIncrement(i);
    sleep(random(50));
  end;
end;



procedure TForm1.HandleTerminate(Sender: Tobject);
begin
Caption := inttostr(i);
end;




procedure TmyThread.OutputMessage(const Amessage: string);
begin
if Assigned(FMainThreadLog) then
    FMainThreadLog.Add(Amessage);
end;


end.

DieDolly 18. Apr 2020 15:18

AW: Delphi einfaches Multithread Beispiel.
 
Das neue Beispiel ist genau so schlimm wie das erste.
Du solltest dir nicht nur ein Video ansehen, sondern am besten in Fachbüchern nachschlagen und lernen, wie man das mit Threads richtig macht.
Ich würde an deiner Stelle aber noch viel weiter vorne anfangen - bei den Grundlagen. Das klingt hart und ich will dich nicht verletzen. Aber dieser Code hat nichts im Unterforum Tutorials zu suchen.

gemy 18. Apr 2020 15:29

AW: Delphi einfaches Multithread Beispiel.
 
Das ist von Coderage 2019 übernommen. Dann hat der wohl auch keine Ahnung.

DieDolly 18. Apr 2020 15:37

AW: Delphi einfaches Multithread Beispiel.
 
Übernehme keinen Code von irgendwoher - außer aus der DP hier ;)
Und ja da hast du recht. Das Beispiel was du übernommen hast ist wirklich gruselig.

gemy 18. Apr 2020 15:38

AW: Delphi einfaches Multithread Beispiel.
 
Das ist der Kanal von Embacadero Germany.

DieDolly 18. Apr 2020 15:44

AW: Delphi einfaches Multithread Beispiel.
 
Ich kann mir nicht vorstellen, dass Embarcaeero Germany solchen Code schreibt.

Jumpy 18. Apr 2020 18:02

AW: Delphi einfaches Multithread Beispiel.
 
Zitat:

Zitat von DieDolly (Beitrag 1462418)
Das neue Beispiel ist genau so schlimm wie das erste.

Ich find so Aussagen immer doof, denn so lernt der TE nix und ich, der ich über den Thread (no pun intended) stolpere, lerne auch nix. Es geht ja scheinbar nur um ein Minimal-Beispiel für mehrere Threads mit Zugriff auf die GUI, das so auch in alten Delphis funktioniert ohne die ganzen neuen Threads-/Paralles-Libraries die es da in und für neue Delphis gibt.

Ich vermute nur warum das Beispiel nicht gut ist, deshalb würde ich mir von den Wissenden konstruktive Aussagen wünschen ala "das ist nicht gut weil", "besser wäre so", "schau mal dieses Beispiel", "diesen Link". Idealerweise dann auf dem Komplexitäts-Niveau auf dem das ursprüngliche Beispiel war, kein Overkill.

Ich hab z.B. nur wenig Ahnung von Threads, sie nur selten benutzt und wenn dann so minimal wie hier. Darum bin ich auf einmal von so Aussagen "Synchronize benutzen ist böse" überrascht. Muss ich das jetzt mit Goto, With und ProcessMessages auf den Dachboden verbannen? Wieso?

p80286 18. Apr 2020 18:49

AW: Delphi einfaches Multithread Beispiel.
 
Zitat:

Zitat von Jumpy (Beitrag 1462427)
Darum bin ich auf einmal von so Aussagen "Synchronize benutzen ist böse" überrascht. Muss ich das jetzt mit Goto, With und ProcessMessages auf den Dachboden verbannen? Wieso?

Wer hat denn gesagt, daß es böse ist? Es ist nur kontraproduktiv. Damit hast Du die Vorteile von 2 Threads über bord geworfen, weil der Mainthread und der Produktivthread voneinnder abhängig sind. danit fällst Du auf das altbekannte
Delphi-Quellcode:
for i:=0 to x do
begin
  machwas;
  if i and $f =0 then
  begin
    label1.caption:=inttostr(i);
    processMessages;
  end;
end;
zurück.

Da ist der Vorteil eines Threads auf ein Minimum geschrumpft.

Man kann damit allerdings für Demonstrationszwecke die ganze Chose einbremsen aber das sollte dann auch explizit gesagt werden.

Gruß
K-H

Jumpy 19. Apr 2020 12:16

AW: Delphi einfaches Multithread Beispiel.
 
Ich verstehe glaub ich was du meinst. Der Thread hält an, während er die GUI über synchronize udated? Und über Postmessage ist das ganze dann mehr entkoppelt? Der Thread setzt sie Message ab und macht weiter. Die GUI fängt bei Gelegenheit die Message ab und verarbeitet sie? Hab ich das so richtig verstanden?

Diese Messages sind doch ein Windows-Ding, oder? Wie macht man das anderswo? Kommen jetzt doch schon die Libraries ins Spiel, wenn man das sauber (aber einfach) machen will?

Es muss ja nicht immer das updaten der GUI sein, ein Thread im Sinne Worker-Thread kann ja seine Ergebnisse mitteilen wollen und sagen, dass er auf neue Aufgaben wartet.

DieDolly 19. Apr 2020 12:17

AW: Delphi einfaches Multithread Beispiel.
 
Zitat:

Und über Postmessage ist das ganze dann mehr entkoppelt? Der Thread setzt sie Message ab und macht weiter. Die GUI fängt bei Gelegenheit die Message ab und verarbeitet sie? Hab ich das so richtig verstanden?
Bei PostMessage ist es so wie du sagst. Bei SendMessage wird gewartet, bist die Nachricht verarbeitet wurde.

p80286 19. Apr 2020 22:19

AW: Delphi einfaches Multithread Beispiel.
 
Zitat:

Zitat von Jumpy (Beitrag 1462447)
Es muss ja nicht immer das updaten der GUI sein, ein Thread im Sinne Worker-Thread kann ja seine Ergebnisse mitteilen wollen und sagen, dass er auf neue Aufgaben wartet.

Mmm gute Frage. Nach meinem Verständnis ist der MainThread der "MasterofDesaster" der sich auch gleichzeitig um die GUI kümmert. Eine empfangene Message muß ja nicht zwangsläufig eine optische Ausgabe ansteuern.

Aber warum sollte ein Thread mehr als eine Aufgabe ausführen. Mir ist das zu komplex. Wenn Dich das interessiert such mal nach ThreadPool. Und das Tut von Michael ist auch recht hilfreich.

Gruß
K-H

Jumpy 20. Apr 2020 11:27

AW: Delphi einfaches Multithread Beispiel.
 
Ich frag da auch nur aus Neugier und gucke gern in diesbezügliche Threads, damit ich schon mal ungefähr was weiß wochach ich googlen muss, wenn ich mal ein konkretes Problem habe.

Scheinbar plant Frank ja da auch was für die Code Rage.

p80286 20. Apr 2020 11:53

AW: Delphi einfaches Multithread Beispiel.
 
Zitat:

Zitat von Jumpy (Beitrag 1462500)
Ich frag da auch nur aus Neugier und gucke gern in diesbezügliche Threads, damit ich schon mal ungefähr was weiß wochach ich googlen muss, wenn ich mal ein konkretes Problem habe.

Scheinbar plant Frank ja da auch was für die Code Rage.

Danke für den Hinweis!

Gruß
K-H


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