AGB  ·  Datenschutz  ·  Impressum  







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

Erste Schritte Multi-Threading

Ein Thema von Ykcim · begonnen am 10. Okt 2023 · letzter Beitrag vom 28. Nov 2023
Antwort Antwort
Seite 1 von 2  1 2      
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
831 Beiträge
 
Delphi 10.4 Sydney
 
#1

Erste Schritte Multi-Threading

  Alt 10. Okt 2023, 23:43
Hallo Zusammen,
ich habe eine Client/Server Applikation, in welcher die Server-App einige aufwändige Abfragen auf unterschiedlichen Datenbanken durchführt.
Diese Abfragen dauern ein paar Sekunden und wenn es unglücklich läuft, blockiert eine Abfrage eine andere. Das gibt dann eine Exception, die zwar abfgefangen werden, aber ich möchte das Ganze gerne in den Griff bekommen.

Daher wage ich mich erstmalig an das Thema Multi-Threading heran.

Ich habe eine ganz banale App geschrieben, in der ich die ersten Versuche bestritte habe und ich würde gerne mal ein Feedback von Euch hören, für die das Routine ist.

Delphi-Quellcode:
unit Frm_Main;

interface

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

type
  TForm1 = class(TForm)
    lbl_eins: TLabel;
    lbl_zwei: TLabel;
    btn_eins: TButton;
    btn_zwei: TButton;
    lbl_Zeit: TLabel;
    Timer1: TTimer;
    Timer_Eins_Start: TButton;
    Timer_Zwei_Start: TButton;
    Timer_Eins_Pause: TButton;
    Timer_Zwei_Pause: TButton;
    Timer_Eins_Resume: TButton;
    Timer_Zwei_Resume: TButton;
    Timer_Eins_Stop: TButton;
    Timer_Zwei_Stop: TButton;
    btn_EinsZwei: TButton;
    procedure btn_einsClick(Sender: TObject);
    procedure btn_zweiClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Timer_Eins_StartClick(Sender: TObject);
    procedure Timer_Eins_ResumeClick(Sender: TObject);
    procedure Timer_Eins_StopClick(Sender: TObject);
    procedure Timer_Zwei_StartClick(Sender: TObject);
    procedure Timer_Eins_PauseClick(Sender: TObject);
    procedure Timer_Zwei_PauseClick(Sender: TObject);
    procedure Timer_Zwei_ResumeClick(Sender: TObject);
    procedure Timer_Zwei_StopClick(Sender: TObject);
    procedure btn_EinsZweiClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    //Alles im Main-Thread
    procedure Timer_Eins;
    procedure Timer_Zwei;
    //Wird vom MyThread aufgerufen
    procedure Write_Counter_Eins(Counter_Eins: integer);
    procedure Write_Counter_Zwei (Counter_Zwei: integer);
    procedure Write_Uhr (Zeit: TTime);
  end;

TMyThread_Eins = class(TThread)
   public
      procedure Execute; override;
end;

TMyThread_Zwei = class(TThread)
   public
      procedure Execute; override;
end;

TMyThread_Uhr = class(TThread)
   public
      procedure Execute; override;
end;

var
  Form1: TForm1;
  TH_Eins: TMyThread_Eins;
  TH_Zwei: TMyThread_Zwei;
  TH_Uhr : TMyThread_Uhr;

implementation

{$R *.dfm}

procedure TForm1.btn_einsClick(Sender: TObject);
begin
   Timer_Eins;
end;

procedure TForm1.btn_zweiClick(Sender: TObject);
begin
   Timer_Zwei;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   //TH_Eins.Free;
   //TH_Zwei.Free;
   TH_Uhr.Free;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
   TH_Uhr := TMyThread_Uhr.Create(False);
end;

procedure TForm1.btn_EinsZweiClick(Sender: TObject);
begin
   TH_Eins := TMyThread_Eins.Create(False);
   TH_Zwei := TMyThread_Zwei.Create(False);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
   lbl_Zeit.Caption := TimeToStr(now());
end;

procedure TForm1.Timer_Eins;
var I: integer;
      sEins: integer;
      c_Eins: integer;
begin
   sEins := 1000;
   c_Eins := 0;
   lbl_eins.Caption := IntToStr(c_Eins);
   lbl_eins.Refresh;
   for I := 0 to 9 do begin
      sleep(sEins);
      INC(c_Eins);
      lbl_eins.Caption := IntToStr(c_Eins);
      lbl_eins.Refresh;
   end;
end;

procedure TForm1.Timer_Zwei;
var I: integer;
      sZwei: integer;
      c_Zwei: integer;
begin
   sZwei := 1000;
   c_Zwei := 0;
   lbl_zwei.Caption := IntToStr(c_Zwei);
   lbl_zwei.Refresh;
   for I := 0 to 9 do begin
      sleep(sZwei);
      INC(c_Zwei);
      lbl_zwei.Caption := IntToStr(c_Zwei);
      lbl_zwei.Refresh;
   end;
end;

procedure TForm1.Timer_Eins_PauseClick(Sender: TObject);
begin
   if not TH_Eins.Terminated then begin
      TH_Eins.Suspend;
   end;
end;

procedure TForm1.Timer_Eins_ResumeClick(Sender: TObject);
begin
   if not TH_Eins.Terminated then begin
      TH_Eins.Resume;
   end;
end;

procedure TForm1.Timer_Eins_StartClick(Sender: TObject);
begin
   TH_Eins := TMyThread_Eins.Create(False);
end;

procedure TForm1.Timer_Eins_StopClick(Sender: TObject);
begin
   TH_Eins.Terminate;
end;

procedure TForm1.Timer_Zwei_PauseClick(Sender: TObject);
begin
   if not TH_Zwei.Terminated then begin
      TH_Zwei.Suspend;
   end;
end;

procedure TForm1.Timer_Zwei_ResumeClick(Sender: TObject);
begin
   if not TH_Zwei.Terminated then begin
      TH_Zwei.Resume;
   end;
end;

procedure TForm1.Timer_Zwei_StartClick(Sender: TObject);
begin
   TH_Zwei := TMyThread_Zwei.Create(False);
end;

procedure TForm1.Timer_Zwei_StopClick(Sender: TObject);
begin
   TH_Zwei.Terminate;
end;

procedure TForm1.Write_Counter_Eins(Counter_Eins: integer);
begin
   lbl_eins.Caption := IntToStr(Counter_Eins);
   lbl_eins.Refresh;
end;

procedure TForm1.Write_Counter_Zwei(Counter_Zwei: integer);
begin
   lbl_zwei.Caption := IntToStr(Counter_Zwei);
   lbl_zwei.Refresh;
end;

procedure TForm1.Write_Uhr(Zeit: TTime);
begin
   lbl_Zeit.Caption := TimeToStr(Zeit);
   lbl_Zeit.Refresh;
end;

{ TMyTread_Eins }

procedure TMyThread_Eins.Execute;
var I: integer;
      sEins: integer;
      c_Eins: integer;
begin
   sEins := 1000;
   c_Eins := 0;
   Synchronize(procedure
               begin
                  Form1.Write_Counter_Eins(c_Eins);
               end);
   for I := 0 to 19 do begin
      if Terminated then begin
         TH_Eins.Free;
         Break;
      end;
      sleep(sEins);
      INC(c_Eins);
      if Terminated then begin
         TH_Eins.Free;
         Break;
      end;
      Synchronize(procedure
                  begin
                     Form1.Write_Counter_Eins(c_Eins);
                  end);
   end;
end;

{ TMyThread_Zwei }

procedure TMyThread_Zwei.Execute;
var I: integer;
      sZwei: integer;
      c_Zwei: integer;
begin
   sZwei := 1000;
   c_Zwei := 0;
   Synchronize(procedure
               begin
                  Form1.Write_Counter_Zwei(c_Zwei);
               end);
   for I := 0 to 19 do begin
      if Terminated then begin
         TH_Zwei.Free;
         Break;
      end;
      sleep(sZwei);
      INC(c_Zwei);
      if Terminated then begin
         TH_Zwei.Free;
         Break;
      end;
      Synchronize(procedure
               begin
                  Form1.Write_Counter_Zwei(c_Zwei);
               end);
   end;
end;

{ TMyThread_Uhr }

procedure TMyThread_Uhr.Execute;
var I: integer;
      sUhr: integer;
begin
   sUhr := 1000;
   while not Terminated do begin
      sleep(sUhr);
      Synchronize(procedure
                  begin
                     Form1.Write_Uhr(Now());
                  end);
   end;

end;

end.
Dann habe ich auch noch zwei konkrete Frage: Wenn ich einen der beiden Threads durch erneutes Klicken des "Eins_Start" starte, während der Thread noch läuft, dass dann quasi ein weiterer Thread gestartet wird. Erkennbar, dass die Ausgabe zwischen den beiden Threads wechselt. Wie ist das möglich? Was für ein Thread wird denn da erzeugt? Ich habe doch mit einer globalen Variable gearbeitet?
Die zweite Frage bezieht sich auf Threads, die zur Laufzeit erzeugt werden: Wie kann ich einen Thread ansprechen, der zur Laufzeit erzeugt wurde? Ich habe das in dem kleinen Programm gelöst, indem ich mit globalen Variablen glöst habe. Aber ich habe keine Lösung gefunden, wie ich einen Thread, der zur Laufzeit ansprechen und z.B. pausieren oder stoppen kann.

Vielen Dank
Patrick
Angehängte Dateien
Dateityp: zip MultiThreading.zip (3,49 MB, 5x aufgerufen)
Patrick
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#2

AW: Erste Schritte Multi-Threading

  Alt 11. Okt 2023, 07:26
Moin...

Ich fange mal an...
Zitat:
Ich habe doch mit einer globalen Variable gearbeitet
...genau deshalb (u.a.) sind die globale Variablen so verpönt.
Zitat:
Wie ist das möglich? Was für ein Thread wird denn da erzeugt?
Du erzeugst eine Thread und legst ihn in die Variable ab. Das ist alles.
ABER: Du tauscht nur den Pointer auf den Thread IN der Variable aus.
Sinnbild:
1. Tasse mit Teebeutel = Thread in der Variable
2. neuer Teebeutel soll in die Tasse = Erzeugung Thread
3. Teebeutel in der Tasse wird auf den Tisch gelegt und der neue Teebeutel kommt in die Tasse.
-> beide Teebeutel existieren. Die Tasse kennt aber nur den Teebeutel in der Tasse.
Zitat:
Wie kann ich einen Thread ansprechen, der zur Laufzeit erzeugt wurde?
Das betrifft auch den obigen Teil. Jeder Thread ist quasi nur ein Pointer in der Variable.
Die Lösung: Verwalte deine Threads in Listen oder Dictionaries (je nach Anwendungsfall). Dann kannst du dir den Thread aus der Liste wieder in eine Variable "laden" und kannst dann damit arbeiten. ...fertsch.
https://docwiki.embarcadero.com/Libr...es.TThreadList

Delphi-Quellcode:
Synchronize(procedure
                  begin
                     Form1.Write_Uhr(Now());
                  end);
Synchronize ist ja soweit ok.
Für die Zukunft aber:
Die Threads sollten eine eigene Unit haben. Der Thread und die Thread Unit, dürfen die Anwesenheit der Form NICHT kennen. Dem Thread muß egal sein was dann passiert.
Thema Wiederverwendbarkeit und zirkuläre Aufrufe.
Lösung:
Im Synchronize mit Events Arbeiten. Das aufrufende Objekt, in deinem Falle die Form, nimmt das Event entgegen und macht in ihrem "Bereich" das was zu zun ist: Write_Uhr(Now)
Beispiel:
Delphi-Quellcode:
Synchronize(procedure
                  begin
                     if Assigned(FOnChangeTime) then
                     begin
                       FOnChangeTime(Self);
                     end;
                  end);
PS:
Bitte vermeide Denglisch. Das tut an den Augen weh.
TH_Eins: TMyThread_Eins; besser
Delphi-Quellcode:
THOne: TMyThreadOne;
...
Bitte keine Unterstriche sondern CamelCase https://de.wikipedia.org/wiki/Binnen...ammiersprachen
Bitte gebe deinen Componenten, auch zum Testen, von Anfang an sprechende Namen. Form1 ist
Miniaturansicht angehängter Grafiken
unterstrich.png  

Geändert von haentschman (11. Okt 2023 um 08:36 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

AW: Erste Schritte Multi-Threading

  Alt 11. Okt 2023, 10:32
Das mit dem Teebeutel geht auch anders auszugrücken.

Neuen Thread erzeugen und in die Tasse hängen


Teebeutel holen (Thread erstellen)
Teebeutel in Tasse hängen + Schnurr um den Hänkel wickeln (Zeiger der Variable zuweisen)
nochmal einen Teebeutel holen (Thread erstellen)
Teebeutel in Tasse hängen + Schnurr um den Hänkel wickeln (Zeiger der Variable zuweisen)
-> alter Zeiger hat in Variable keinen Platz und wird überschrieben = Schurr abschneiden und neue Schnurr drumwickeln -> Beutel bleibt aber in der Tasse (du beendest ja den alten Thread nicht)
$2B or not $2B
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
353 Beiträge
 
#4

AW: Erste Schritte Multi-Threading

  Alt 11. Okt 2023, 11:45
Cup, Tea and bag.... ?!!!!
Leave that stuff to the English, replace them with cars and car equipment's, though i remember Uwe love car examples, or wait... may be he did hate them ,
can't remember now, all i have that there is some emotional connection between Uwe and cars.
Kas
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
831 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Erste Schritte Multi-Threading

  Alt 23. Nov 2023, 16:24
Hallo Zusammen,

vielen Dank für Eure Erklärungen und Hinweise! Ich habe versucht diese umzusetzen (außer DENGLISCH, das habe ich jetzt nicht angefasst ), bin aber trotz intensiver Suche an ziemlich allen Fronten gescheitert.

Ich habe dann versucht schrittweise vorzugehen und die Threads erst einmal in eine eigene Unit auszulagern.
Weil es mir noch nicht gelungen ist, ein Event zu definieren, habe ich die Form in die uses gepackt.

Die TThreadUnit

Delphi-Quellcode:
unit TMyThreadUnit;

interface

uses Windows,
      Messages,
      SysUtils,
      Classes,
      Graphics,
      Controls,
      Forms;

type



TMyThreads = class
      strict protected

      private

      public
         constructor Create;
end;


TMyThread_Eins = class(TThread)
   public
      procedure Execute; override;
end;

TMyThread_Zwei = class(TThread)
   public
      procedure Execute; override;
end;

TMyThread_Uhr = class(TThread)
   public
      procedure Execute; override;
end;

var MyThreads: TMyThreads;
      TH_Eins: TMyThread_Eins;
      TH_Zwei: TMyThread_Zwei;
      TH_Uhr : TMyThread_Uhr;


{ TMyThreads }

implementation

uses Frm_Main;

{ TMyThreads }

constructor TMyThreads.Create;
begin

end;

{ TMyTread_Eins }

procedure TMyThread_Eins.Execute;
var I: integer;
      sEins: integer;
      c_Eins: integer;
begin
   sEins := 1000;
   c_Eins := 0;
   Synchronize(procedure
               begin
                  Form1.Write_Counter_Eins(c_Eins);
               end);
   for I := 0 to 19 do begin
      if Terminated then begin
         TH_Eins.Free;
         Break;
      end;
      sleep(sEins);
      INC(c_Eins);
      if Terminated then begin
         TH_Eins.Free;
         Break;
      end;
      Synchronize(procedure
                  begin
                     Form1.Write_Counter_Eins(c_Eins);
                  end);
   end;
end;

{ TMyThread_Zwei }

procedure TMyThread_Zwei.Execute;
var I: integer;
      sZwei: integer;
      c_Zwei: integer;
begin
   sZwei := 1000;
   c_Zwei := 0;
   Synchronize(procedure
               begin
                  Form1.Write_Counter_Zwei(c_Zwei);
               end);
   for I := 0 to 19 do begin
      if Terminated then begin
         TH_Zwei.Free;
         Break;
      end;
      sleep(sZwei);
      INC(c_Zwei);
      if Terminated then begin
         TH_Zwei.Free;
         Break;
      end;
      Synchronize(procedure
               begin
                  Form1.Write_Counter_Zwei(c_Zwei);
               end);
   end;
end;

{ TMyThread_Uhr }

procedure TMyThread_Uhr.Execute;
var I: integer;
      sUhr: integer;
begin
   sUhr := 1000;
   while not Terminated do begin
      sleep(sUhr);
      Synchronize(procedure
                  begin
                     Form1.Write_Uhr(Now());
                  end);
   end;

end;



end.
Und dann die Aufrufe in der Form:

Delphi-Quellcode:
unit Frm_Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, TMyThreadUnit;

type
   TForm1 = class(TForm)
      lbl_eins: TLabel;
      lbl_zwei: TLabel;
      btn_eins: TButton;
      btn_zwei: TButton;
      lbl_Zeit: TLabel;
      Timer1: TTimer;
      Timer_Eins_Start: TButton;
      Timer_Zwei_Start: TButton;
      Timer_Eins_Pause: TButton;
      Timer_Zwei_Pause: TButton;
      Timer_Eins_Resume: TButton;
      Timer_Zwei_Resume: TButton;
      Timer_Eins_Stop: TButton;
      Timer_Zwei_Stop: TButton;
      btn_EinsZwei: TButton;
      procedure btn_einsClick(Sender: TObject);
      procedure btn_zweiClick(Sender: TObject);
      procedure Timer1Timer(Sender: TObject);
      procedure Timer_Eins_StartClick(Sender: TObject);
      procedure Timer_Eins_ResumeClick(Sender: TObject);
      procedure Timer_Eins_StopClick(Sender: TObject);
      procedure Timer_Zwei_StartClick(Sender: TObject);
      procedure Timer_Eins_PauseClick(Sender: TObject);
      procedure Timer_Zwei_PauseClick(Sender: TObject);
      procedure Timer_Zwei_ResumeClick(Sender: TObject);
      procedure Timer_Zwei_StopClick(Sender: TObject);
      procedure btn_EinsZweiClick(Sender: TObject);
      procedure FormShow(Sender: TObject);
      procedure FormClose(Sender: TObject; var Action: TCloseAction);
   private
      { Private-Deklarationen }
   public
      { Public-Deklarationen }
      //Alles im Main-Thread
      procedure Timer_Eins;
      procedure Timer_Zwei;
      //Wird vom MyThread aufgerufen
      procedure Write_Counter_Eins(Counter_Eins: integer);
      procedure Write_Counter_Zwei (Counter_Zwei: integer);
      procedure Write_Uhr (Zeit: TTime);

   end;



var
  Form1: TForm1;


implementation
//uses TMyThreadUnit;

{$R *.dfm}


procedure TForm1.btn_einsClick(Sender: TObject);
begin
   Timer_Eins;
end;

procedure TForm1.btn_zweiClick(Sender: TObject);
begin
   Timer_Zwei;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   TH_Uhr.Free;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
   TH_Uhr := TMyThread_Uhr.Create(False);
end;

procedure TForm1.btn_EinsZweiClick(Sender: TObject);
begin
   TH_Eins := TMyThread_Eins.Create(False);
   TH_Zwei := TMyThread_Zwei.Create(False);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
   lbl_Zeit.Caption := TimeToStr(now());
end;

procedure TForm1.Timer_Eins;
var I: integer;
      sEins: integer;
      c_Eins: integer;
begin
   sEins := 1000;
   c_Eins := 0;
   lbl_eins.Caption := IntToStr(c_Eins);
   lbl_eins.Refresh;
   for I := 0 to 9 do begin
      sleep(sEins);
      INC(c_Eins);
      lbl_eins.Caption := IntToStr(c_Eins);
      lbl_eins.Refresh;
   end;
end;

procedure TForm1.Timer_Zwei;
var I: integer;
      sZwei: integer;
      c_Zwei: integer;
begin
   sZwei := 1000;
   c_Zwei := 0;
   lbl_zwei.Caption := IntToStr(c_Zwei);
   lbl_zwei.Refresh;
   for I := 0 to 9 do begin
      sleep(sZwei);
      INC(c_Zwei);
      lbl_zwei.Caption := IntToStr(c_Zwei);
      lbl_zwei.Refresh;
   end;
end;

procedure TForm1.Timer_Eins_PauseClick(Sender: TObject);
begin
   if not TH_Eins.Terminated then begin //Auf protected Symbol TThread.Terminated kann nicht zugegriffen werden
      TH_Eins.Suspend;
   end;
end;

procedure TForm1.Timer_Eins_ResumeClick(Sender: TObject);
begin
   if not TH_Eins.Terminated then begin //Auf protected Symbol TThread.Terminated kann nicht zugegriffen werden
     TMyThreadUnit.TH_Eins.Resume;
   end;
end;

procedure TForm1.Timer_Eins_StartClick(Sender: TObject);
begin
   TH_Eins := TMyThread_Eins.Create(False);
end;

procedure TForm1.Timer_Eins_StopClick(Sender: TObject);
begin
   TH_Eins.Terminate;
end;

procedure TForm1.Timer_Zwei_PauseClick(Sender: TObject);
begin
   if not TH_Zwei.Terminated then begin //Auf protected Symbol TThread.Terminated kann nicht zugegriffen werden
      TH_Zwei.Suspend;
   end;
end;

procedure TForm1.Timer_Zwei_ResumeClick(Sender: TObject);
begin
   if not TH_Zwei.Terminated then begin //Auf protected Symbol TThread.Terminated kann nicht zugegriffen werden
      TH_Zwei.Resume;
   end;
end;

procedure TForm1.Timer_Zwei_StartClick(Sender: TObject);
begin
   TH_Zwei := TMyThread_Zwei.Create(False);
end;

procedure TForm1.Timer_Zwei_StopClick(Sender: TObject);
begin
   TH_Zwei.Terminate;
end;

procedure TForm1.Write_Counter_Eins(Counter_Eins: integer);
begin
   lbl_eins.Caption := IntToStr(Counter_Eins);
   lbl_eins.Refresh;
end;

procedure TForm1.Write_Counter_Zwei(Counter_Zwei: integer);
begin
   lbl_zwei.Caption := IntToStr(Counter_Zwei);
   lbl_zwei.Refresh;
end;

procedure TForm1.Write_Uhr(Zeit: TTime);
begin
   lbl_Zeit.Caption := TimeToStr(Zeit);
   lbl_Zeit.Refresh;
end;

end.
Aber ich mache anscheinend grundlegende Fehler in dem Aufbau der ThreadUnit. Ich kann das Programm so nicht kompilieren, weil TH_Eins.Terminated von der Form aus nicht geprüft werden kann.

Daher meine Fragen:
1. Wie muss ich die ThreadUnit aufbauen? Ich muss ja für jeden Thread einen eigenen Typen definieren...
2. Hat jemand vielleicht ein einfaches Beispiel, wie ich das mit dem Event lösen muss?

Vielen Dank
Patrick
Patrick
  Mit Zitat antworten Zitat
Benutzerbild von Sherlock
Sherlock

Registriert seit: 10. Jan 2006
Ort: Offenbach
3.800 Beiträge
 
Delphi 12 Athens
 
#6

AW: Erste Schritte Multi-Threading

  Alt 23. Nov 2023, 16:37
Zu Events hilft eventuell als Einstieg die...Hilfe: http://docwiki.embarcadero.com/RADSt...gnisse_(Delphi)
Oliver
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
831 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Erste Schritte Multi-Threading

  Alt 27. Nov 2023, 14:09
Hallo Sherlock,

vielen Dank für den Link. Leider läuft der ins Leere... Hast Du noch einen funktionierenden?

Vielen Dank
Patrick
Patrick
  Mit Zitat antworten Zitat
Benutzerbild von dummzeuch
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
1.623 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: Erste Schritte Multi-Threading

  Alt 27. Nov 2023, 14:10
vielen Dank für den Link. Leider läuft der ins Leere... Hast Du noch einen funktionierenden?
Da fehlte ein ")" am Ende:
http://docwiki.embarcadero.com/RADSt...gnisse_(Delphi)
Thomas Mueller
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
831 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Erste Schritte Multi-Threading

  Alt 27. Nov 2023, 14:32
Vielen Dank!

Jetzt funktioniert der Link!

Kann mir noch jemand einen Tip geben, wie ich die Thread-Unit aufbauen sollte? Da steckt noch der Wurm drin...

LG Patrick
Patrick
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

AW: Erste Schritte Multi-Threading

  Alt 27. Nov 2023, 14:40
Bei dir auch.
[URL] selbst drumrumschreiben, oder den Link-Button benutzen.

Leider sind automatische Links zu doof, einfach die ) mitzunehmen, wenn im Link eine ( drin ist.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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