Autor Beitrag
LittleBen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Do 08.09.11 11:07 
Hallo,
wollte euch fragen, ob das so OK ist, wie die Progressbar laufen lasse:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
type
  TMyThread = class(TThread)
  private
    FProgressBar: TProgressBar;
    procedure SetProgressBar(const Value: TProgressBar) ;
  protected
    procedure execute; override;
  public
    constructor Create;
    property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
  end;

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TMyThread.Execute;
var n: integer;
begin
 try
  FProgressbar.Position:= 0;
  FProgressbar.Max:= 100;

  for n:= 0 to 100 do
   FProgressbar.Position:= FProgressbar.Position+1;
 except
  on e: exception do;
 end;
end;

constructor TMyThread.Create;
begin
 inherited Create(true); 
 FreeOnTerminate:= true;
end;

ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TMyThread.SetProgressBar(const Value: TProgressBar) ;
begin
 FProgressBar:= Value;
end;
Kann ich das so machen, ohne die Regeln des Threaden zu brechen?

Viele Grüße,
Benny


Moderiert von user profile iconNarses: Topic aus Sonstiges (Delphi) verschoben am Do 08.09.2011 um 21:27
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Do 08.09.11 11:41 
Ein ganz klares "Nein": Eine Progressbar ist eine visuelle Komponente, und es gilt:
ausblenden Quelltext
1:
Visuelle Komponenten + zweiter Thread = Furchtbar Böse™.					

Zugriff auf die VCL von einem zweiten Thread aus ist nur per Synchronize oder vergleichbaren Techniken erlaubt.

_________________
We are, we were and will not be.
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Do 08.09.11 11:44 
Ah, also habe ichs doch falsch gemacht. Also brauche ich eine Procedure die in der Schleife Synchronisiert wird?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 08.09.11 12:07 
Nein, übergib dem Thread einfach das Handle der ProgressBar und setze mit PBM_SETPOS direkt die Position. ;-)
msdn.microsoft.com/e...ibrary/bb760844.aspx

// EDIT:
Das sieht so aus als würdest du hier den Thread pausiert starten, mit Resume fortsetzen und per FreeOnTerminate freigeben? Ganz böse. ;-)
(Ja, ich weiß, bei deinen Delphiversionen war Resume noch nicht entsprechend markiert. ;-))

Übergib das Handle lieber in einem eigenen Konstruktor und lasse den Thread sofort loslaufen.
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Do 08.09.11 12:14 
Wie ist das denn passiert? Entschuldigung für den Doppelpost. War keine absicht!


Zuletzt bearbeitet von LittleBen am Do 08.09.11 12:39, insgesamt 1-mal bearbeitet
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Do 08.09.11 12:32 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das sieht so aus als würdest du hier den Thread pausiert starten, mit Resume fortsetzen und per FreeOnTerminate freigeben? Ganz böse.
Echt, ist das böse? Habe es so in irgendwelchen Tutorials gesehen. Wie mache ich es dann?

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Nein, übergib dem Thread einfach das Handle der ProgressBar und setze mit PBM_SETPOS direkt die Position.
Mhh, ist das nicht ein bisschen unsauber?

EDIT: Darf ich das so machen?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TMyThread.Execute;
var n: integer;
begin
 try
  for n:= 0 to 100 do
   Synchronize(Refresh);
 except
  on e: exception do;
 end;
end;

procedure TMyThread.Refresh;
begin
 FProgressbar.Position:= FProgressbar.Position + 1;
end;

constructor TMyThread.Create;
begin
 inherited Create(true); 
 FreeOnTerminate:= true;
end;
Andreas L.
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1703
Erhaltene Danke: 25

Windows Vista / Windows 10
Delphi 2009 Pro (JVCL, DragDrop, rmKlever, ICS, EmbeddedWB, DEC, Indy)
BeitragVerfasst: Do 08.09.11 13:04 
Sinnvoller wäre es über ein Ereignis:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
  TMyOnProgressEvent = procedure(APos, AMax: Integer) of object;
  
  TMyThread = class(TThread)
  private
    FOnProgress: TMyOnProgressEvent;
  published
    property OnProgress: TMyOnProgressEvent read FOnProgress write FOnProgress;
  end;

...

procedure TMyThread.Execute;
begin

  for i := 0 to 100 do
  begin
    if Assigned(FOnprogress) then
      Synchronize(OnProgress(i, 100));
  end;


end;
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Do 08.09.11 13:13 
Dann bekomme ich die Fehlermeldung: [Fehler] U_Main.pas(120): Es gibt keine überladene Version von 'Synchronize', die man mit diesen Argumenten aufrufen kann

EDIT:

So darf ich das doch machen, oder?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
type
  TMyThread = class(TThread)
  private
    FProgressBar: TProgressBar;
    procedure DoProgress;
    procedure SetProgressBar(const Value: TProgressBar) ;
  protected
    procedure execute; override;
  public
    constructor Create;
    property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
  end;

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TMyThread.Execute;
var n: integer;
begin
 try
  for n:= 0 to 100 do
     Synchronize(DoProgress) ;
  except
  on e: exception do;
 end;

end;

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TMyThread.SetProgressBar(const Value: TProgressBar) ;
begin
 FProgressBar:= Value;
end;

procedure TMyThread.DoProgress;
begin
 FProgressBar.Position:= FProgressBar.Position+1;
end;
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 08.09.11 13:39 
Synchronisieren ist hier wenig sinnvoll...

Schließlich soll die Operation durch den Thread doch gerade vom Hauptthread abgekoppelt werden. Und dann für die Fortschrittsanzeige zu synchronisieren... :shock:

user profile iconLittleBen hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das sieht so aus als würdest du hier den Thread pausiert starten, mit Resume fortsetzen und per FreeOnTerminate freigeben? Ganz böse.
Echt, ist das böse? Habe es so in irgendwelchen Tutorials gesehen. Wie mache ich es dann?
Das Problem ist, dass der Thread schon fertig sein kann, bevor Resume selbst durch ist. Und dann knallt es.
Deshalb ist Resume mittlerweile auch als veraltet markiert. Es sollte schlicht nie verwendet werden. Wozu auch? Die Startparameter kannst du als Parameter mitgeben und warten kannst du mit TEvent oder ähnlichem, wenn der Start verzögert werden soll.

user profile iconLittleBen hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Nein, übergib dem Thread einfach das Handle der ProgressBar und setze mit PBM_SETPOS direkt die Position.
Mhh, ist das nicht ein bisschen unsauber?
Nein, warum? Das ist genau der beste Weg hier.
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Do 08.09.11 13:58 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Synchronisieren ist hier wenig sinnvoll...
Schließlich soll die Operation durch den Thread doch gerade vom Hauptthread abgekoppelt werden. Und dann für die Fortschrittsanzeige zu synchronisieren... :shock:
Stimmt, das macht kein Sinn. Hab ich von hier abgeschaut: delphi.about.com/od/...ead/a/thread-gui.htm

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Nein, übergib dem Thread einfach das Handle der ProgressBar und setze mit PBM_SETPOS direkt die Position.
Kannst du mir das bitte erklären. Verstehe das mit dem PBM_SETPOS nicht.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 08.09.11 14:08 
Ich weiß nicht genau wo jetzt das Problem liegt?
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
uses
  CommCtrl;

  TMyLittleThread = class(TThread)
  private
    FProgressBarHandle: THandle;
  protected
    procedure Execute; override;
  public
    constructor Create(AProgressBarHandle: THandle);
  end;

constructor TMyLittleThread.Create(AProgressBarHandle: THandle);
begin
  FProgressBarHandle := AProgressBarHandle;
  FreeOnTerminate := True;
  inherited Create(False);
end;

procedure TMyLittleThread.Execute;
var
  i: Integer;
begin
  for i := 1 to 100 do
  begin
    SendMessage(FProgressBarHandle, PBM_SETPOS, i, 0);
    Sleep(100);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TMyLittleThread.Create(ProgressBar1.Handle);
end;

Für diesen Beitrag haben gedankt: LittleBen
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Do 08.09.11 14:19 
Ahhhh, so meinst du das! Vielen Dank!
Wenn ich auch noch ein Memo beschreiben will, dann kann ich dass ja auch mit Sendmessage machen, oder?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 08.09.11 14:26 
Klar:
ausblenden Delphi-Quelltext
1:
2:
    SendMessage(FMemoHandle, WM_SETTEXT, 0, lParam(PChar(IntToStr(i))));
    SendMessage(FMemoHandle, CM_TEXTCHANGED, 00);

Für diesen Beitrag haben gedankt: LittleBen
LittleBen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 258
Erhaltene Danke: 4

Win 7, Mac OS
Delphi 7
BeitragVerfasst: Do 08.09.11 14:28 
Perfekt!!! Vielen Dank, hast mir mal wieder geholfen!