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.