Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Formular in Thread auslagern

  Alt 3. Feb 2014, 13:29
ShowModal?
Bis zum WaitFor kommt der dann ja nicht, falls nicht jemand vorher das Fenster schließt.

Wäre es da nicht andersrum besser?
Delphi-Quellcode:
var
  LForm : TForm;
  LThread : TThread;
begin
  LForm := TSplashScreen.Create(nil);
  try
    LThread := TStartupThread.Create(LForm);
    try
      LForm.Show;
      LThread.WaitFor;
      LForm.Hide;
    finally
      LThread.Free;
    end;
  finally
    LForm.Free;
  end;
end;

// oder

var
  LForm : TForm;
  LThread : TThread;
begin
  LThread := TStartupThread.Create;
  try
    LForm := TSplashScreen.Create(nil);
    try
      LForm.Show;
      LThread.WaitFor;
    finally
      LForm.Free;
    end;
  finally
    LThread.Free;
  end;
end;

Wie schon erwähnt, müssen die VCL-Komponenten im Hauptthread VCL-Thread bleiben.

Man könnte zwar in anderen Threads direkt via WinAPI Formulare nzeigen, aber diese müssen dann komplett in dem Thread erstellt, behandelt und freigegeben werden, inkl. eigener Message-Loop.
Bei deiner Variante wird der MainThread aber blockiert
Delphi-Quellcode:
LForm.Show;
// Wir befinden uns im MainThread-Context und da tut sich jetzt nichts mehr, bis der Thread abgearbeitet ist
LThread.WaitFor;
und das ist bei meiner Variante eben genau nicht der Fall.

TStartupThread muss lediglich am Ende eine Nachricht an die Form schicken, damit die geschlossen wird.
Hier mal so ein Beispiel StartupThread
Delphi-Quellcode:
unit StartupThread;

interface

uses
  FormThreadWait,
  System.SysUtils,
  Classes;

type
  TStartupThread = class( TThread )
  private
    FCloseForm : TThreadProcedure;
    FInfoToForm : TProc<string>;
    procedure InfoToForm( const AInfo : string );
  protected
    procedure DoExecute; virtual;
    procedure Execute; override;
  public
    constructor Create( AForm : TThreadWaitForm );
  end;

implementation

{ TStartupThread }

constructor TStartupThread.Create( AForm : TThreadWaitForm );
begin
  inherited Create( False );
  // Anonyme Methode zum Schließen der Form
  FCloseForm := procedure
    begin
      AForm.Close;
    end;
  FInfoToForm := procedure( AInfo : string )
    begin
      AForm.Label1.Caption := AInfo;
    end;
end;

procedure TStartupThread.DoExecute;
var
  LIdx : Integer;
begin
  InfoToForm( 'Initialisierung...' );
  Sleep( 500 );
  for LIdx := 1 to 20 do
  begin
    InfoToForm( 'Schritt ' + IntToStr( LIdx ) );
    Sleep( 250 );
  end;
end;

procedure TStartupThread.Execute;
begin
  inherited;
  try
    DoExecute;
  finally
    // Form schließen synchronisiert abschicken
    // Queue würde auch gehen, aber was sollen wir in der Zwischenzeit noch machen, wir sind fertig ;o)
    Synchronize( FCloseForm );
  end;
end;

procedure TStartupThread.InfoToForm( const AInfo : string );
begin
  Queue(
      procedure
    begin
      FInfoToForm( AInfo );
    end );
end;

end.
Anwendung im Anhang (kompiliert und als Source)
Angehängte Dateien
Dateityp: zip dp_178908.zip (809,1 KB, 44x aufgerufen)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat