我想从多个线程/进程写入名为'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写入消息吗?
答案 0 :(得分:3)
您的选择都没有任何好处。你需要使用选项3!
重点是所有对UI控件的访问都必须在主线程上执行。使用TThread.Synchronize
或TThread.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选项可用。但是我认为你在使用术语过程时会说错话。我怀疑你不是指进程,但你的意思是,我不知道。