Thema: Delphi Threads und Eventhandler

Einzelnen Beitrag anzeigen

Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.272 Beiträge
 
Delphi 10.4 Sydney
 
#1

Threads und Eventhandler

  Alt 10. Mär 2019, 19:45
Hallo!

Ich mache gerade meine ersten Schritte in Multithreading und da klemmt es gerade dabei, Eventhandler richtig anzusprechen. Hier ein stark vereinfachtes Testprogramm, dass das Problem verdeutlichen soll. Soweit ich das verstehe hat der Thread trotz EnterCriticalSection keinen Zugriff auf die Eventhandler-Methodenzeiger der Instanz von TmyClass. Nur warum verstehe ich gerade nicht so recht. Da wäre ich für ein paar Tips dankbar.

Um eine Diskussion gleich zu vermeiden: Ich verwende NOCH kein TThread weil das hier auf einem Demoprogramm aufbaut an dem ich mich erstmal orientieren will. Daher bitte keine "Mit TThread wär das nicht passiert"-Diskussion Wenn ich mal sicherer bin im Umgang mit Threads, dann mache ich auch eigene Konstruktionen in der Art.

Stürmische Grüße
Cody

Delphi-Quellcode:
unit Test;

interface

uses
  System.Classes, Vcl.Controls, Winapi.Windows;

type
  TmyClass = class(TObject)
  private
    FOnFailed: TNotifyEvent;
    FOnStarted: TNotifyEvent;
  protected
    procedure DoFailed;
    procedure DoStarted;
  public
    constructor Create;
    destructor Destroy; override;

    procedure Produce;

    property OnFailed: TNotifyEvent read FOnFailed write FOnFailed;
    property OnStarted: TNotifyEvent read FOnStarted write FOnStarted;
  end;
  
  TForm1 = class(TForm)
   procedure DoOnFailed(Sender: TObject);
   procedure DoOnStarted(Sender: TObject);
   procedure Form1Create(Sender: TObject);
   procedure Form1Destroy(Sender: TObject);
   procedure Button1Click(Sender: TObject);
  end;

var
  FThreadId: DWord;

implementation

uses
  System.SysUtils;

var
  CS: TRTLCriticalSection;
  myClass: TmyClass;
  
{ TmyClass }

constructor TmyClass.Create;
begin
  FStreamHandle := 0;
  FThreadId := 0;
end;

destructor TmyClass.Destroy;
begin
  { .. }
  inherited;
end;

procedure TmyClass.DoFailed;
begin
  if Assigned(FOnFailed) then begin // <-- FOnFailed = NIL **WARUM??**
    FOnFailed(Self);
  end;
end;

procedure TmyClass.DoStarted;
begin
  if Assigned(FOnStarted) then begin // <-- FOnStarted = NIL **WARUM??**
    FOnStarted(Self);
  end;
end;

procedure TmyClass.Produce;
var
  Dummy: Cardinal;
  Func: TThreadFunc;
  Status: Boolean;

  function _ThreadFunc: Integer;
  begin
    Result := 0;
    Status := MachIrgendwas;
    EnterCriticalSection(CS);
    try
      if Status then begin
        DoStarted;
      end else begin
        DoFailed;
      end;
    finally
      LeaveCriticalSection(CS);
    end;
    FThreadId := 0;
  end;

begin
  if FThreadId = 0 then begin
    FThreadId := BeginThread(nil, 0, @_ThreadFunc, Nil, 0, Dummy);
  end;
end;

{ TForm1 }

procedure Form1Create(Sender: TObject);
begin
  myClass := TmyClass.Create;
  myClass.OnFailed := DoOnFailed;
  myClass.OnStarted := DoOnStarted;
end;

procedure Form1Destroy(Sender: TObject);
begin
  FreeAndNil(myClass);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  myClass.Produce;
end;

initialization

  InitializeCriticalSection(CS);

finalization

  DeleteCriticalSection(CS);

end.
Ich mache grundsätzlich keine Screenshots. Schießen auf Bildschirme gibt nämlich hässliche Pixelfehler und schadet der Gesundheit vom Kollegen gegenüber. I und E zu vertauschen hätte den selben negativen Effekt, würde aber eher dem Betriebsklima schaden
  Mit Zitat antworten Zitat