应用程序在将消息发布到之前未显示的框架后挂起
Application hangs after posting message to previously not shown frame
我有 PageControl
和两个 TabSheets
。他们每个人都有一个Frame
,我们称之为Frame2
。我有一个后台线程,它在完成任务后向 Frame2
发送消息。 Frame2
在第二个 TabSheet
上,因此当用户启动应用程序时它是不可见的。
问题是,当线程向 Frame2
发布消息时,我的应用程序停止刷新其内容,但前提是 Frame2
之前未显示过。这使我认为 Frame2
的消息队列尚未初始化,并且当 Frame2
首次显示在屏幕上时它被初始化。我猜对了吗?
有人可以告诉我如何在构建 Frame2
后立即初始化消息队列以便它可以立即收听消息吗?
并不是框架没有消息队列——是线程有消息队列,而不是windows——而是框架还没有window句柄。 window 句柄很可能只在框架首次显示时创建,除非你 post 它是一条消息,在这种情况下 window 是按需创建的。
如果您尝试 post 向它发送消息,您可能会收到这样的语句:PostMessage(Frame2.Handle, ...)
.
读取组件的 Handle
属性 将导致该组件创建其 window,如果它还没有句柄。当您的辅助线程中发生这种情况时,将创建属于该辅助线程的框架 window。这可能会导致许多问题。与所有 VCL windows 一样,框架的 window 需要属于主 VCL 线程。
即使您确保在将消息定向到它之前在主线程中创建了框架的句柄(例如通过在主线程中调用 HandleNeeded
),仍然有可能读取框架的 Handle
属性 会出问题。这是因为 VCL 控件可能 重新创建 它的 window。然后,再次读取 Handle
属性 可能会在错误的线程中触发框架的 window 的创建。
安全技术是框架调用 AllocateHWnd
来创建专用消息 window。在框架的构造函数中执行此操作,以确保它在主线程中发生,然后 post 消息在那里。当您创建 window 时,您将提供一个回调方法,该方法将在 window 收到消息时随时调用。该回调方法应属于框架控件,以便它可以访问与其关联的框架的所有字段和方法。
我有 PageControl
和两个 TabSheets
。他们每个人都有一个Frame
,我们称之为Frame2
。我有一个后台线程,它在完成任务后向 Frame2
发送消息。 Frame2
在第二个 TabSheet
上,因此当用户启动应用程序时它是不可见的。
问题是,当线程向 Frame2
发布消息时,我的应用程序停止刷新其内容,但前提是 Frame2
之前未显示过。这使我认为 Frame2
的消息队列尚未初始化,并且当 Frame2
首次显示在屏幕上时它被初始化。我猜对了吗?
有人可以告诉我如何在构建 Frame2
后立即初始化消息队列以便它可以立即收听消息吗?
并不是框架没有消息队列——是线程有消息队列,而不是windows——而是框架还没有window句柄。 window 句柄很可能只在框架首次显示时创建,除非你 post 它是一条消息,在这种情况下 window 是按需创建的。
如果您尝试 post 向它发送消息,您可能会收到这样的语句:PostMessage(Frame2.Handle, ...)
.
读取组件的 Handle
属性 将导致该组件创建其 window,如果它还没有句柄。当您的辅助线程中发生这种情况时,将创建属于该辅助线程的框架 window。这可能会导致许多问题。与所有 VCL windows 一样,框架的 window 需要属于主 VCL 线程。
即使您确保在将消息定向到它之前在主线程中创建了框架的句柄(例如通过在主线程中调用 HandleNeeded
),仍然有可能读取框架的 Handle
属性 会出问题。这是因为 VCL 控件可能 重新创建 它的 window。然后,再次读取 Handle
属性 可能会在错误的线程中触发框架的 window 的创建。
安全技术是框架调用 AllocateHWnd
来创建专用消息 window。在框架的构造函数中执行此操作,以确保它在主线程中发生,然后 post 消息在那里。当您创建 window 时,您将提供一个回调方法,该方法将在 window 收到消息时随时调用。该回调方法应属于框架控件,以便它可以访问与其关联的框架的所有字段和方法。