da ich mich als absoluten Anfänger in Bezug auf Multi-Threading betrachte, in dem Forum hier.
Ich habe ein Programm (mit GUI zur Eingabe der Parameter) geschrieben (in Delphi und Lazarus), das ein und dieselbe Rechnung für eine größere Anzahl an Elementen (einige wenige bis zu ca. 120; je nach Problemgröße) durchführen muss. Das funktioniert soweit linear. Aber da bietet sich eine parallele Verarbeitung natürlich an.
Beim Einlesen in das Thema habe ich schnell gelernt, dass GUI und Multi-Thead so seine Fallstricke hat. Also habe ich nach einem kleinen Beispiel gesucht und bin über das hier gestolpert:
https://www.thoughtco.com/synchronizing ... on-1058159
und habe das nachgebaut.
Code: Alles auswählen
unit MT_MainForm;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls;
type
TButton = class(StdCtrls.TButton)
OwnedThread: TThread;
ProgressBar: TProgressBar;
end;
TMyThread = class(TThread)
private
FCounter: Integer;
FCountTo: Integer;
FProgressBar: TProgressBar;
FOwnerButton: TButton;
procedure DoProgress;
procedure SetCountTo(const Value: Integer) ;
procedure SetProgressBar(const Value: TProgressBar) ;
procedure SetOwnerButton(const Value: TButton) ;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean) ;
property CountTo: Integer read FCountTo write SetCountTo;
property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
property OwnerButton: TButton read FOwnerButton write SetOwnerButton;
end;
{ TMainForm }
TMainForm = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
ProgressBar1: TProgressBar;
ProgressBar2: TProgressBar;
ProgressBar3: TProgressBar;
ProgressBar4: TProgressBar;
ProgressBar5: TProgressBar;
private
public
end;
var
MainForm: TMainForm;
implementation
{$R *.lfm}
{ TMyThread }
constructor TMyThread.Create(CreateSuspended: Boolean) ;
begin
inherited;
FCounter := 0;
FCountTo := MAXINT;
end;
procedure TMyThread.DoProgress;
var
PctDone: Extended;
begin
PctDone := (FCounter / FCountTo) ;
FProgressBar.Position := Round(FProgressBar.Step * PctDone) ;
FOwnerButton.Caption := FormatFloat('0.00 %', PctDone * 100) ;
end;
procedure TMyThread.Execute;
const
Interval = 1000000;
begin
FreeOnTerminate := True;
FProgressBar.Max := FCountTo div Interval;
FProgressBar.Step := FProgressBar.Max;
while FCounter < FCountTo do
begin
if FCounter mod Interval = 0 then
Synchronize(DoProgress) ;
Inc(FCounter) ;
end;
FOwnerButton.Caption := 'Start';
FOwnerButton.OwnedThread := nil;
FProgressBar.Position := FProgressBar.Max;
end;
procedure TMyThread.SetCountTo(const Value: Integer) ;
begin
FCountTo := Value;
end;
procedure TMyThread.SetOwnerButton(const Value: TButton) ;
begin
FOwnerButton := Value;
end;
procedure TMyThread.SetProgressBar(const Value: TProgressBar) ;
begin
FProgressBar := Value;
end;
procedure TMainForm.Button1Click(Sender: TObject) ;
var
aButton: TButton;
aThread: TMyThread;
aProgressBar: TProgressBar;
begin
aButton := TButton(Sender) ;
if not Assigned(aButton.OwnedThread) then
begin
aThread := TMyThread.Create(True) ;
aButton.OwnedThread := aThread;
aProgressBar :=
TProgressBar(FindComponent(StringReplace(aButton.Name, 'Button', 'ProgressBar', []))) ;
aThread.ProgressBar := aProgressBar;
aThread.OwnerButton := aButton;
aThread.Resume;
aButton.Caption := 'Pause';
end
else
begin
if aButton.OwnedThread.Suspended then
aButton.OwnedThread.Resume
else
aButton.OwnedThread.Suspend;
aButton.Caption := 'Run';
end;
end;
end.
Code: Alles auswählen
Projekt kompilieren, Ziel: MultThread: Exit code 1, Fehler: 1
mt_mainform.pas(12,5) Error: Only classes which are compiled in $M+ mode can be published
Code: Alles auswählen
TButton = class(StdCtrls.TButton)
OwnedThread: TThread;
ProgressBar: TProgressBar;
end;
Und: gibt es vielleicht einen besseren Einstieg in das Thema Multi-Threading - idealerweise mit (lauffähigem Beispiel-Code)?
Dankbar für jeden Hinweis,
Photor