Extra Thread starten
Moin Moin!
Ich versuche mich gerade mal an der Programmierung eines Extra Threads. Mein Kunstwerk:
Delphi-Quellcode:
Es soll also während des durchlaufens eine Schleife ein Indicator animiert werden und nach Durchlauf wieder deanmiert werden. Passieren tut beim Start des Programms nichts. Ein Indicator erscheint nicht. Das Label bleibt bei 0.
unit MainFormUnit;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.WinXCtrls, Vcl.ExtCtrls; type TheThread = class(TThread) protected procedure Execute; override; end; type TMainForm = class(TForm) Indicator: TActivityIndicator; CounterLabel: TLabel; StartThreadBtn: TButton; procedure StartThreadBtnClick(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var MainForm: TMainForm; Thread: TheThread; implementation {$R *.dfm} // ************************************************* procedure TheThread.Execute; begin MainForm.Indicator.Animate := true; end; // ************************************************* procedure TMainForm.StartBtnClick(Sender: TObject); begin try // Thread starten Thread := TheThread.Create(True); Thread.Resume; // eine reine Beschäftigungsaufgabe für den Hauptthread for I := 0 to 100 do begin MainForm.CounterLabel.Caption := I.tostring; Sleep(500); end; // Feierabend Thread.Terminate; Thread.FreeOnTerminate := True; MainForm.Indicator.Animate := false; except on E:Exception do begin Thread.Terminate; Thread.FreeOnTerminate := True; MainForm.Indicator.Animate := false; end; end; end. Ich hatte das bis hier so verstanden, das ich den Hauptthread starte - also das Formular wird angezeigt, dann schmeisse ich per StartBtn einen weiteren Thread an, der den Animator anzeigt und diese Schleife durchläuft. Ist die durch ist Ende. Tja, natürlich habe ich auch die Sychronize Sache gesehen, aber was soll ich hier sychronisieren? Was mache ich falsch? creehawk |
AW: Extra Thread starten
1. Deine "Arbeit" findet noch immer im Main-Thread statt und dieser blockiert die Nachrichtenschleife. Die Arbeit muss außerhalb des Main-Threads stattfinden.
2. Threads dürfen nicht unsynchronisiert auf die GUI zugreifen. Änderungen in der GUI müssen im Takt des Main-Threads stattfinden. synchronize tthread ... ...:cat:... |
AW: Extra Thread starten
Zitat:
Einfach runtergeschrieben und nicht getestet, aber dafür vermutlich mehr wie es gedacht ist.
Delphi-Quellcode:
unit MainFormUnit;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.WinXCtrls, Vcl.ExtCtrls; type TheThread = class(TThread) private procedure DoIt; public procedure Execute; override; end; type TMainForm = class(TForm) Indicator: TActivityIndicator; CounterLabel: TLabel; StartThreadBtn: TButton; procedure StartThreadBtnClick(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var MainForm: TMainForm; implementation {$R *.dfm} // ************************************************* procedure TheThread.DoIt; begin MainForm.Indicator.Animate := true; end; procedure TheThread.Execute; begin Synchronize(DoIt); end; // ************************************************* procedure TMainForm.StartBtnClick(Sender: TObject); var Thread: TheThread; I: integer; begin try // Thread starten Thread := TheThread.Create(True); Thread.FreeOnTerminate := true; Thread.Resume; // eine reine Beschäftigungsaufgabe für den Hauptthread for I := 0 to 100 do begin MainForm.CounterLabel.Caption := I.tostring; Application.ProcessMessages; Sleep(500); end; MainForm.Indicator.Animate := false; except on E:Exception do begin MainForm.Indicator.Animate := false; end; end; end. |
AW: Extra Thread starten
Okay, also doch sychronisieren.
Allerdings läuft der Indicator jetzt nicht rund sondern ruckartig. Wird denn mit Synchronize die Animate Anweisung nicht immer wieder aufgrufen? Ziel der ganzen Sache ist einfach einen Indicator anzuzeigen, während eine XML Datei erzeugt wird, was so 15 Sekunden dauert. creehawk |
AW: Extra Thread starten
Der Fehler ist, dass du die Verarbeitung der XML-Datei im Hauptthread machst. Du musst das im Thread erledigen. Dann hast du im Hauptthread auch keine Blockade bei der Anzeige mehr.
|
AW: Extra Thread starten
Zitat:
|
AW: Extra Thread starten
Dann nimm für die Zeitanzeige einen Timer.
Und es geht natürlich auch ohne Synchronize.
Delphi-Quellcode:
interface
uses Classes, SyncObjs, Forms, WinXCtrls, StdCtrls, ExtCtrls; type TheThread = class(TThread) constructor Create(CreateSuspendet: Boolean); destructor Destroy; override; private FValue: Integer; protected FCS: TCriticalSection; procedure Execute; override; function GetValue: Integer; procedure SetValue(AValue: Integer); public property Value: Integer read GetValue write SetValue; end; type TMainForm = class(TForm) Indicator: TActivityIndicator; CounterLabel: TLabel; StartThreadBtn: TButton; Timer: TTimer; procedure StartBtnClick(Sender: TObject); procedure DoOnTimer(Sender: TObject); procedure DoOnTerminate(Sender: TObject); private { Private-Deklarationen } FThread: TheThread; public { Public-Deklarationen } end; var MainForm: TMainForm; implementation {$R *.dfm} uses SysUtils; // ************************************************* constructor TheThread.Create(CreateSuspendet: Boolean); begin FCS := TCriticalSection.Create; inherited; end; destructor TheThread.Destroy; begin inherited; FCS.Free; end; procedure TheThread.Execute; var I: Integer; begin try for I := 0 to 100 do begin Value := I; // MainForm.CounterLabel.Caption Sleep(500); end; except // hier Fehlerbehandlung aller Fehler im Thread end; end; function TheThread.GetValue: Integer; begin FCS.Enter; try Result := FValue; finally FCS.Release; end; end; procedure TheThread.SetValue(AValue: Integer); begin FCS.Enter; try FValue := AValue; finally FCS.Release; end; end; // ************************************************* procedure TMainForm.StartBtnClick(Sender: TObject); begin MainForm.Indicator.Animate := True; Timer.Enabled := True; // Thread starten FThread := TheThread.Create(True); FThread.FreeOnTerminate := True; FThread.OnTerminate := DoOnTerminate; FThread.Resume; end; procedure TMainForm.DoOnTimer(Sender: TObject); begin if Assigned(FThread) then begin MainForm.CounterLabel.Caption := IntToStr(FThread.Value); end; end; procedure TMainForm.DoOnTerminate(Sender: TObject); begin MainForm.Indicator.Animate := False; Timer.Enabled := False; FThread := nil; end; end. |
AW: Extra Thread starten
Vielfältigen Dank für die Antworten!
Jetzt habe ich die Zusammenhänge (hoffentlich) verstanden. Auf in die Schlacht. creehawk |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:33 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