问题
I want to write from multiple threads/processes to a TListBox called 'listMessages' and I have this two procedures in order to do this :
1- With adding object :
procedure Log(Msg: String; Color: TColor);
begin
listMessages.Items.AddObject(Msg, Pointer(Color));
listMessages.ItemIndex := listMessages.Items.Count -1;
end;
2- With TIdCriticalSection called 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;
Can you tell me which is best(fast + thread safe) or show me a third way to write messages to my TListBox from my threads/processes ?
回答1:
Neither of your options is any good. You need to use option 3!
The point is that all access to UI controls must execute on the main thread. Use TThread.Synchronize
or TThread.Queue
to marshal UI code onto the main UI thread. Once you do this, the code will not need any further serialization because the very act of getting it to run on the UI thread serializes it.
The code might look like this:
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;
In your update you state that you need to write to the list box from a different process. This cannot be achieved with any of the code in the question. You need inter-process communication (IPC) for that. Sending windows messages would be a reasonable approach to take, but there are other IPC options available. But I think that you mis-speak when you use the term process. I suspect that you don't mean process, but what you do mean, I have no idea.
来源:https://stackoverflow.com/questions/24551490/delphi-asynchronous-write-to-tlistbox