Passing value to synchronize thread

delphi, multithreading

Solution

Look at the various declarations of `TThread.Synchronize()`. You are trying to call the version that takes a `TThreadMethod` as input. `TThreadMethod` is parameter-less:

TThreadMethod = procedure of object;

That is why passing just `t.Proc` works but passing `t.Proc('foo')` does not.

With that said, you are completely misusing `TThread.Synchronize()`. You don't need to create a `TThread` object in order to use the static version of `Synchronize()`. And if you do create a `TThread` object, make it actually do something, like this:

type
  TSendThread = class(TThread)
  public
    fStr: String;
    procedure DoProc;
    procedure Proc(const S: string);
  protected
    procedure Execute; override;
  end;

  procedure TSendThread.Execute;
  begin
    Proc('foo');
  end;

  procedure TSendThread.Proc(const S: string);
  begin
    fStr := S;
    Synchronize(DoProc);
  end;

  procedure TSendThread.DoProc;
  begin
    ShowMessage(fStr);
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  t : TSendThread;
begin
  t := TSendThread.Create(False);
  t.WaitFor;
  t.Free;
end;

However, because you are using XE4, `Synchronize()` also supports anonymous procedures as well, which would eliminate your `TSendThread` class completely in this example, eg:

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.Synchronize(nil,
    procedure
    begin
      ShowMessage('foo');
    end
  );
end;

Update: given new info about what you REALLY want to do with your thread, you need to go about it like this instead:

type
  TSendThread = class(TThread)
  private
    fURL, fMethod, fParam: string;
  protected
    procedure Execute; override;
  public
    constructor Create(aURL, aMethod, aParam: string);
  end;

constructor TSendThread.Create(aURL, aMethod, aParam: string);
begin
  inherited Create(False);
  fURL := aUrl;
  fMethod := aMethod;
  fParam := aParam;
end;

procedure TSendThread.Execute;
begin
  // use fURL, fMethod, and fParam as needed...
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  t : TSendThread;
begin
  t := TSendThread.Create('url', 'method', 'param');
  ...
end;

Or like this:

type
  TSendThread = class(TThread)
  private
    fURL, fMethod, fParam: string;
    procedure GetValues;
  protected
    procedure Execute; override;
  end;

procedure TSendThread.GetValues;
begin
  fURL := ...;
  fMethod := ...;
  fParam := ...;
end;

procedure TSendThread.Execute;
begin
  Synchronize(GetValues);
  // use fURL, fMethod, and fParam as needed...
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  t : TSendThread;
begin
  t := TSendThread.Create(False);
  ...
end;

Problem

I'm new to thread, so i've been trying with this for hours (i'm using XE4), i have a simple thread ``` type TSendThread = class(TThread) private public procedure proc(const s : string); protected procedure Execute; override; end; procedure TSendThread.proc(const S: String); begin showmessage(s); end; ``` Now, in my main form, i want to call that "proc" with : ``` procedure TForm1.Button1Click(Sender: TObject); var t : TSendThread; begin t := TSendThread.create(true); t.Synchronize(nil, t.proc('foo')); end; ``` But whenever i try t compile that i get : There is no overloaded version of 'Synchronize' that can be called with these arguments that does not make sense (to me) because when i remove the "S" parameter from "proc" it works fine.

Original source