Is TThread passing object to main thread via Synchronise OK?

137 views Asked by At

I want to check the following code, in particular Execute method,to ensure it's not doing anything super dodgy. This code is Delphi 2007, btw.

I am passing back to the main thread via synchronize a reference to an object (FToken) created in the execute method of the thread.

I am only doing this after the FToken is created in TTokenThread.Execute

Is this OK in terms of thread safety?

Critique most welcome.

Type

  TExceptionNotifyEvent = procedure(Const Error : String) of object;
  TTokenNotifyEvent = procedure(const Token : AccessToken) of object;

  TTokenThread = class(TThread)
  private
     FTokenNotifyEvent : TTokenNotifyEvent;
     FOnException : TExceptionNotifyEvent;
     FExceptionMsg : String;
     FToken : AccessToken;
     procedure HandleException(const E : Exception);
     procedure DoException;
     procedure DoSynchronise;
  public
     constructor Create;
     destructor Destroy;override;
     procedure Execute; override;
     procedure WhenException(const OnException : TExceptionNotifyEvent);
     procedure WhenToken(const TokenNotify : TTokenNotifyEvent);
  end;




{ TTokenThread }
constructor TTokenThread.Create;
begin
  inherited create(true);
  FreeOnTerminate := true;
end;

destructor TTokenThread.Destroy;
begin
  if assigned(FToken) then FToken.free;
  inherited;
end;

procedure TTokenThread.Execute;
begin
  inherited;
  try
    FToken := RESTAdapter.GetAccessToken();
    synchronize(DoSynchronise);
  except on
    E:Exception do
    begin
      handleException(E);
    end;
  end;
end;

procedure TTokenThread.HandleException(const E: Exception);
begin
  if terminated then exit;
  FExceptionMsg := E.Message;
  synchronize(DoException); //synch call with the main thread (this is potentially blocking)
  Terminate;
end;

procedure TTokenThread.WhenException(const OnException: TExceptionNotifyEvent);
begin
  FOnException := OnException;
end;

procedure TTokenThread.WhenToken(const TokenNotify: TTokenNotifyEvent);
begin
  FTokenNotifyEvent := TokenNotify;
end;

procedure TTokenThread.DoException ;
begin
  if assigned(FOnException) then FOnException(FExceptionMsg);
end;


procedure TTokenThread.DoSynchronise;
begin
  if assigned(FTokenNotifyEvent) and assigned(FToken) then FTokenNotifyEvent(FToken);
end;

calling code


procedure TForm3.ProcessToken(const Token : AccessToken);
begin
  if assigned(Token) then
  begin
      memo1.lines.clear;
      memo1.lines.add(format('access_token: %s',[Token.Token]));
      memo1.lines.add(format('expires_in: %s',[inttostr(Token.ExpiryUtc)]));
      memo1.lines.add(format('token_type: %s',[token.type2]));
      memo1.lines.add(format('scope: %s',[token.scope]));
  end;
end;



procedure TForm3.BtnAccessTokenClick(Sender: TObject);
var
  TokenThread : TTokenThread;
begin
  TokenThread := TTokenThread.create;
  TokenThread.WhenToken(ProcessToken);
  TokenThread.Resume;
end;


0

There are 0 answers