1

我想从多个线程/进程写入一个名为'listMessages'的TListBox,我有这两个过程来做到这一点:

1-添加对象:

procedure Log(Msg: String; Color: TColor);
begin
  listMessages.Items.AddObject(Msg, Pointer(Color));
  listMessages.ItemIndex := listMessages.Items.Count -1;
end;

2- 使用 TIdCriticalSection 称为protectListMessages

procedure TMainForm.safelyLogMessage(mess : String);
begin
  protectlistMessages.Enter;
  try
    listMessages.Items.Add(mess);
    listMessages.ItemIndex := listMessages.Items.Count -1;
  finally
    protectListMessages.Leave;
  end;
end; 

你能告诉我哪个是最好的(快速+线程安全)还是告诉我第三种方法从我的线程/进程向我的 TListBox 写入消息?

4

1 回答 1

4

你的两个选择都不好。您需要使用选项 3!

关键是所有对 UI 控件的访问都必须在主线程上执行。使用TThread.SynchronizeTThread.Queue将 UI 代码编组到主 UI 线程。一旦你这样做了,代码将不需要任何进一步的序列化,因为让它在 UI 线程上运行的行为会序列化它。

代码可能如下所示:

procedure TMainForm.Log(const Msg: string; const Color: TColor);
var
  Proc: TThreadProcedure;
begin
  Proc :=
    procedure
    begin
      ListBox1.AddItem(Msg, Pointer(Color));
      ListBox1.ItemIndex := ListBox1.Count-1;
    end;

  if GetCurrentThreadId = MainThreadID then
    Proc()
  else
    TThread.Queue(nil, Proc);
end;

在您的更新中,您声明您需要从不同的进程写入列表框。问题中的任何代码都无法实现这一点。为此,您需要进程间通信(IPC)。发送 Windows 消息将是一种合理的方法,但还有其他可用的 IPC 选项。但是我认为您在使用术语过程时说错了。我怀疑你的意思不是过程,但你的意思是什么,我不知道。

于 2014-07-03T11:14:40.607 回答