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

前端 未结 3 1194
情书的邮戳
情书的邮戳 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:24

    About GDI thread safety in Windows, see this reference article.

    It clearly states that you can access safely handles from multiple threads, but that it should not be made at the same time. You need to protect access to GDI handles, e.g. using critical sections.

    Remember that GDI handles, like most Windows handles, are pointers of internal structures mapped to an integer (NativeUInt under newer Windows, for 64 bit compatibility). Like always in multi-thread computing, accessing the same content concurrently can be source of problems, which are very difficult to identify and fix.

    The UI part of the VCL itself was never meant to be thread-safe, from the beginning, since it was relying on the non-thread-safe Windows API. For instance, if you release a GDI object in a thread, which is still needed in another thread, you'll face potential GPF.

    Embarcadero (at this time) could have made the VCL thread-safe, serializing all UI access via critical sections, but it may have added complexity, and decreased overall performance. Note that even Microsoft .Net platform (in both WinForms and WPF) also requires a dedicated thread for UI access, AFAIK.

    So, to refresh UI from multiple threads, you have several patterns:

    1. Use Synchronize calls from the thread;
    2. Send a GDI custom message (see WM_USER) from the background threads to notify the UI thread that a refresh is needed;
    3. Have a stateless approach: the UI will refresh its content from time to time, from the logic layer (using a timer or when you press some buttons which may change the data).

    From my point of view, I prefer option 2 for most UIs, and an additional option 3 (which can be mixed with option 2) for remote client-server access. Therefore, you do not have to want from the server side to trigger some update event to the UI. In a HTTP/AJAX RESTful world, this does definitively make sense. Option 1 is somewhat slow, IMHO. In all cases, options 2 and 3 expect a clear n-Tier layered architecture, in which logic and UI are not mixed: but this is a good pattern to follow anyway, for any serious development.

提交回复
热议问题