Updating VCL from the same thread that created the UI. Why?

前端 未结 3 1188
情书的邮戳
情书的邮戳 2021-02-04 16:37

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

3条回答
  •  死守一世寂寞
    2021-02-04 17:01

    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 HWNDs 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 HWNDs 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.

提交回复
热议问题