从创建UI的同一个线程更新VCL。为什么? [英] Updating VCL from the same thread that created the UI. Why?

查看:141
本文介绍了从创建UI的同一个线程更新VCL。为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道我必须调用Synchronize来从没有创建控件或向窗口发送消息的线程更新vcl。



我经常听到这个词不是线程安全的,但是我找不到关于发生什么的实际解释。



我知道应用程序可能会因访问冲突而崩溃,但是我又不知道为什么?



请详细说明这个主题。

解决方案

线程安全在Windows中,请参阅此参考文章



它清楚地表明,您可以从多个线程 安全地访问句柄,不应该在同一时间。您需要保护对GDI句柄的访问,例如使用关键部分。



记住,像大多数Windows句柄一样,GDI句柄是映射到的内部结构的指针在较新的Windows下,为64位兼容性的整数 NativeUInt )。像多线程计算一样,同时访问相同的内容可能是问题的根源,这很难识别和修复。



VCL本身的UI部分从一开始,从来没有意图是线程安全的,因为它依赖于非线程安全的Windows API。例如,如果您在线程中释放GDI对象,这在另一个线程中仍然需要,您将面临潜在的GPF。 Embarcadero(此时)可能使VCL线程安全,通过关键部分序列化所有UI访问,但可能会增加复杂性,降低整体性能。请注意,即使是微软.Net平台(在 WinForms WPF )也需要一个用于UI访问的专用线程AFAIK。



因此,要从多个线程中刷新UI,您有以下几种模式:


  1. 使用同步线程调用;

  2. 从后台线程发送一个GDI自定义消息(见 WM_USER ),通知UI线程需要刷新;

  3. 具有无状态方式:UI将不时刷新其内容,从逻辑层(使用定时器或按某些按钮可能会更改数据)

从我的角度来看,我更喜欢大多数UI的选项2,还有一个附加选项3(可以与选项2)混合,用于远程客户端 - 服务器访问。因此,您不需要从服务器端触发UI更新事件。在HTTP / AJAX RESTful 世界中,这绝对有意义。备选方案1有点慢,IMHO。在所有情况下,选项2和3都希望有一个明确的 n层分层架构,其中逻辑和UI不混合,但这是一个很好的模式,无论如何,任何严重的发展。


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 thread safe but I can't find an actual explanation about what is happening.

I know the application might crash with an access violation, but again I don't know why?

Please shed a light on this topic.

解决方案

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.

这篇关于从创建UI的同一个线程更新VCL。为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆