How to do something similar to C# Invoke() in Delphi?

Viewed 139

I'm writing a project with Delphi. I need to do something to do the function that the Invoke method in C# does. I saw the Synchronize() method do this somewhere, but I don't know exactly how to write it. How can I do it ?

C# code:

private void ListenerOnDataTransmit(DataTransmitEventArgs e)
{
    transmittedMsg = BitConverter.ToString(e.TransmittedBytes, 0, e.TransmittedBytes.Length);

    //I want to write here 
    try { Invoke(new EventHandler(UpdateTransmittedMessagesListView)); }
    catch { }
}

// UpdateTransmittedMessagesListView 
public void UpdateTransmittedMessagesListView(object sender, EventArgs e)
{
    ListViewItem item = new ListViewItem(DateTime.Now.ToLongTimeString());
    item.SubItems.Add(transmittedMsg);
    lvTransmittedMessages.Items.Insert(0, item);
    if (lvTransmittedMessages.Items.Count > 100)
        lvTransmittedMessages.Items.Clear();
}

public MainForm()
{
    InitializeComponent();   
    plistener.OnDataTransmit += new DataTransmitEventHandler(ListenerOnDataTransmit);
}

The codes are like this, I want to do the operations on the Invoke line in the first function.

1 Answers

In C#, the Invoke() method "Executes a delegate on the thread that owns the control's underlying window handle".

In Delphi, UI controls are (supposed to be) owned by the main UI thread. You can use the TThread.Synchronize() or TThread.Queue() method to execute code from a worker thread in the context of the main UI thread, eg:

type
  TWorkerThread = class(TThread)
  private
    FData: string;
    procedure DoUpdate;
  protected
    procedure Execute; override;
  end;

procedure TWorkerThread.Execute;
begin
  ...
  FData := ...;
  Synchronize(DoUpdate);
  ...
end;

procedure TWorkerThread.DoUpdate;
var
  Item: TListItem;
begin
  Item := MyForm.lvTransmittedMessages.Items.Add;
  Item.Caption := DateTimeToStr(Now);
  Item.SubItems.Add(FData);
  if MyForm.lvTransmittedMessages.Items.Count > 100 then
    MyForm.lvTransmittedMessages.Items.Clear;
end;

Alternatively:

procedure SomeWorkerThreadProc;
var
  s: string;
begin
  s := ...;

  TThread.Synchronize(nil,
    procedure
    var
      Item: TListItem;
    begin
      Item := MyForm.lvTransmittedMessages.Items.Add;
      Item.Caption := DateTimeToStr(Now);
      Item.SubItems.Add(s);
      if MyForm.lvTransmittedMessages.Items.Count > 100 then
        MyForm.lvTransmittedMessages.Items.Clear;
    end
  );
end;
Related