AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Delphi einfaches Multithread Beispiel.
Tutorial durchsuchen
Ansicht
Themen-Optionen

Delphi einfaches Multithread Beispiel.

Ein Tutorial von gemy · begonnen am 12. Apr 2020 · letzter Beitrag vom 20. Apr 2020
Antwort Antwort
Seite 2 von 4     12 34      
gemy
Registriert seit: 17. Feb 2019
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

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.

Geändert von gemy (19. Apr 2020 um 14:40 Uhr)
 
Benutzerbild von p80286
p80286

 
FreePascal / Lazarus
 
#11
  Alt 13. Apr 2020, 14:02
Ja, Nein, ist es nicht.

INC x im Assembler ist nicht thread-safe, allerdings 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
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

 
Delphi 12 Athens
 
#12
  Alt 13. Apr 2020, 14:37
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.
Uwe Raabe
  Mit Zitat antworten Zitat
Redeemer

 
Delphi 2009 Professional
 
#13
  Alt 13. Apr 2020, 17:27
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.
Janni
  Mit Zitat antworten Zitat
Benutzerbild von Gausi
Gausi

 
Delphi 11 Alexandria
 
#14
  Alt 13. Apr 2020, 19:01
Gut, dann lag ich ja richtig.

@Redeemer: danke für den Link. Schau ich mir bei Gelegenheit mal genauer an!
  Mit Zitat antworten Zitat
gemy
 
#15
  Alt 13. Apr 2020, 19:15
habe mir nun https://www.youtube.com/watch?v=WOc89TF8l-8 angesehen.

Wie kann ich den thread löschen ?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

 
Delphi 12 Athens
 
#16
  Alt 13. Apr 2020, 19:26
@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.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

 
Delphi 12 Athens
 
#17
  Alt 13. Apr 2020, 19:29
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.

Geändert von himitsu (13. Apr 2020 um 19:31 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

 
FreePascal / Lazarus
 
#18
  Alt 13. Apr 2020, 19:54
@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
  Mit Zitat antworten Zitat
Redeemer

 
Delphi 2009 Professional
 
#19
  Alt 13. Apr 2020, 21:07
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.
Janni
  Mit Zitat antworten Zitat
Benutzerbild von Sherlock
Sherlock

 
Delphi 12 Athens
 
#20
  Alt 14. Apr 2020, 08:41
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
Oliver
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 4     12 34      


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 19:17 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