I know that I must call Synchronize to update the vcl from a thread that did not create the controls or send a message to the window.
I have often heard the word not th
One of the biggest causes of the thread-unsafety in the VCL UI controls is the TWinControl.Handle
property getter. It is not just a simple read-only accessor of the control's HWND
. It also creates the HWND
if it does not exist yet. If a worker thread reads the Handle
property when no HWND
exists yet, it creates a new HWND
within the worker thread context, which is bad because HWND
s are tied to the creating thread context, which would render the owning control pretty much inoperable at best since Windows messages for the control would not go through the main message loop anymore. But worse, if the main thread reads the same Handle
property at the same time the worker thread does (for instance, if the main thread is dynamically recreating the Handle
for any number of reasons), there is a race condition between which thread context creates the HWND
that gets assigned as the new Handle
, as well as a potential handle leak potential if both threads end up creating new HWND
s but only one can be kept and the other gets leaked.
Another offender to thread-unsafety is the VCL's MakeObjectInstance()
function, which the VCL uses internally for assigning the TWinControl.WndProc()
non-static class method as the message procedure of the TWinControl.Handle
window, as well as assigning anyTWndMethod
-typed object method as the message procedure of the HWND
created by the AllocateHWnd()
function (used by TTimer
for example). MakeObjectInstance()
does quite a bit of memory allocating/caching and twiddling of that memory content which are not protected from concurrent access by multiple threads.
If you can ensure a control's Handle
is allocated ahead of time, and if you can ensure the main thread never recreates that Handle
while the worker thread is running, then it is possible to safely send messages to that control from the worker thread without using Synchronize()
. But it is not advisable, there are just too many factors that the worker thread would have to take into account. That is why it is best that all UI access be done in the main thread only. That is how the VCL UI system is meant to be used.