multithreading - 从创建 UI 的同一线程更新 VCL。为什么?

标签 multithreading delphi thread-safety

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

我经常听到“线程不安全”这个词,但我找不到关于正在发生的事情的实际解释。

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

请阐明这个主题。

最佳答案

VCL UI 控件中线程不安全的最大原因之一是 TWinControl.Handle 属性 getter。它不仅仅是控件的 HWND 的简单只读访问器。如果 HWND 尚不存在,它还会创建它。如果工作线程在尚不存在 HWND 时读取 Handle 属性,则会在工作线程上下文中创建一个新的 HWND,这是不好的,因为HWND 与创建线程上下文相关联,这最多会使所属控件几乎无法操作,因为该控件的 Windows 消息将不再通过主消息循环。但更糟糕的是,如果主线程与工作线程同时读取相同的 Handle 属性(例如,如果主线程为任意数量动态地重新创建 Handle原因),线程上下文创建被分配为新的 HandleHWND 之间存在竞争条件,并且如果两个线程都结束,则存在潜在的句柄泄漏可能性创建新的 HWND,但只有一个可以保留,另一个会泄漏。

线程不安全的另一个罪魁祸首是 VCL 的 MakeObjectInstance() 函数,VCL 在内部使用该函数将 TWinControl.WndProc() 非静态类方法分配为TWinControl.Handle 窗口的消息过程,以及指定任何 TWndMethod 类型的对象方法作为由AllocateHWnd() 函数(例如 TTimer 使用)。 MakeObjectInstance() 对内存内容进行了大量的内存分配/缓存和调整,这些内存内容不受多线程并发访问的保护。

如果您可以确保提前分配控件的Handle,并且如果您可以确保主线程永远不会重新创建该在工作线程运行时进行处理,然后就可以从工作线程安全地向该控件发送消息,而无需使用Synchronize()。但这是不可取的,工作线程需要考虑的因素太多了。这就是为什么所有 UI 访问最好仅在主线程中完成的原因。这就是 VCL UI 系统的用途。

关于multithreading - 从创建 UI 的同一线程更新 VCL。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10648996/

相关文章:

java - 蒙特卡罗在多个线程上计算 Pi

multithreading - ServerEndpoint 的每个方法是否由不同的线程执行?

android - onBackPressed 和 android 中的线程

delphi - 如何在DLL(Delphi/TJVPluginManager + TJvPlugin)中实现回调方法

delphi - 嵌入式 PC 网络摄像头 delphi 应用程序不断弹出视频捕获对话框

Java 线程等待通知

Delphi HTTP 应用程序在将文件加载到流中时引发错误

objective-c - NSThread 拾取队列并处理它

python - pymysql连接线程安全吗? pymysql游标线程安全吗?

java - 在 intellij Idea 中检查类的线程安全