问题描述
在线程(不是主线程)内调用 Application.Processmessages
是否“可以”,还是应该预料到麻烦?
解决方法
TApplication.ProcessMessages()
主要用于处理 VCL 消息。您不应在工作线程中接收任何 VCL 消息,除非您正在从工作线程创建和显示 TForm
窗口。您不应该这样做,因为 VCL 不是线程安全的,不应在主 UI 线程之外使用。
但是,话虽如此,如果在工作线程中没有收到 VCL 消息,在工作线程中调用 ProcessMessages()
本身并没有什么害处。它会将任何接收到的消息(VCL 或其他)发送到调用线程中的适当窗口过程。但是,如果您认为需要在工作线程中手动发送消息,那么您首先确实需要质疑为什么需要这样做。除非您在工作线程中使用 COM 单元线程对象,或者将自定义线程消息发布到工作线程,否则在工作线程中运行消息循环几乎没有用,即使那样 ProcessMessages()
也不是理想的目的。
从主线程以外的线程调用 Application.ProcessMessages
确实是个坏主意,因为它确实是针对 VCL 的,而 VCL 不是线程安全的。
话虽如此,我有很多线程都有一个 message loop
以便它处理协作多任务和线程间通信。
我总是通过调用 Windows API 来编写自己的消息循环:
while GetMessage(MsgRec,0) do begin
TranslateMessage(MsgRec);
DispatchMessage(MsgRec)
end;
当异步 TWSocket 必须在线程中运行时,我会在我的 ICS(Internet 组件套件)中大量使用它。上面的代码是 TicsWndControl 中 ICS 的一部分。 TWSocket 每个线程可以轻松处理数百个连接,但如果要处理数千个连接,则必须使用线程。
在工作线程或主线程和工作线程之间使用 Windows 消息通常是一种避免调用 TThread.Synchronize
的解决方案:当您从一个线程 PostMessage 时,发送线程继续运行,而接收线程(创建的线程) PostMessage 中传递的窗口句柄)将在他自己的上下文中优雅地处理消息。