Sending a string from anonymous thread to UI with PostMessage
Create an object containing the string as a property and pass the pointer to the object as Integer LParam. Then, in the message handler, use the string and free the object. In this way, you could not only send strings but also other data as well.

unit SendingStringWithPostMessageUsingObjectMainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

const
  WM_STRINGMESSAGE = WM_USER;

type
  TStrMsgObject = class(TObject)
  private
    fMsg: string;
  public
    constructor Create(const aMsg: string);
    property Msg: string read fMsg;
  end;

type
  TForm2 = class(TForm)
    btnSetCaption: TButton;
    btnChangeCaption: TButton;
    procedure btnChangeCaptionClick(Sender: TObject);
    procedure btnSetCaptionClick(Sender: TObject);
  private
    { Private declarations }
    procedure WMStringMessage(var Msg: TMessage); message WM_STRINGMESSAGE;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

const
  // WM_STRINGMESSAGE Actions:
  ACTION_SETCAPTION    = 0;
  ACTION_CHANGECAPTION = 1;

constructor TStrMsgObject.Create(const aMsg: string);
begin
  inherited Create;
  fMsg := aMsg;
end;

procedure TForm2.WMStringMessage(var Msg: TMessage);
// Process WM_STRINGMESSAGE messages
var
  mo: TStrMsgObject;
begin
  mo := TStrMsgObject(Msg.LParam);
  try
    case Msg.WParam of
      ACTION_SETCAPTION:
        begin
          Caption := mo.Msg;
        end;
      ACTION_CHANGECAPTION:
        begin
          Caption := Caption + mo.Msg;
        end;
    end
  finally
    mo.Free;
  end;
end;

procedure TForm2.btnSetCaptionClick(Sender: TObject);
begin
  System.Classes.TThread.CreateAnonymousThread(
    procedure
    begin
      PostMessage(Handle, WM_STRINGMESSAGE, ACTION_SETCAPTION, Integer(TStrMsgObject.Create('My new caption')));
    end).Start;
end;

procedure TForm2.btnChangeCaptionClick(Sender: TObject);
begin
  System.Classes.TThread.CreateAnonymousThread(
    procedure
    begin
      PostMessage(Handle, WM_STRINGMESSAGE, ACTION_CHANGECAPTION, Integer(TStrMsgObject.Create(' changed')));
    end).Start;
end;

end.