Einzelnen Beitrag anzeigen

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