I have PageControl
with two TabSheets
. On each of them there is a Frame
, lets call it Frame2
. I have a background thread which is posting message to Frame2
when it has finished its task. The Frame2
is on the second TabSheet
so it is not visible when user starts application.
The problem is that my application stops refreshing its content when the thread posted message to Frame2
, but only in case when Frame2
has not been previously shown. This leads me to think that message queue for the Frame2
has not yet been initialized and it gets initialized when the Frame2
is shown on the screen for the first time. Am I guessing correct?
Could someone give me tips how to initialize message queue right after constructing the Frame2
so it could listen messages immediately?
However, this prevents the average user from closing and restarting a hung application and often ends in a reboot. The operating system defines an application hang as a UI thread that has not processed messages for at least 5 seconds.
After 5 seconds, they will try to terminate a hung application. Next to crashes, application hangs are the most common source of user disruption when working with Win32 applications. There are many different root causes for application hangs, and not all of them manifest themselves in an unresponsive UI.
There are many different root causes for application hangs, and not all of them manifest themselves in an unresponsive UI. However, an unresponsive UI is one of the most common hang experiences, and this scenario currently receives the most operating system support for both detection as well as recovery.
The operating system defines an application hang as a UI thread that has not processed messages for at least 5 seconds. Obvious bugs cause some hangs, for example, a thread waiting for an event that is never signaled, and two threads each holding a lock and trying to acquire the others.
It's not that the frame doesn't have a message queue — it's threads that have message queues, not windows — but that the frame doesn't yet have a window handle. The window handle is most likely only created when the frame is first shown, unless you post it a message, in which case the window is created on demand.
If you attempt to post a message to it, you probably have a statement like this: PostMessage(Frame2.Handle, ...)
.
Reading the Handle
property of a component will cause that component to create its window, if it doesn't already have a handle. When that happens in your secondary thread, then the frame's window is created belonging to that secondary thread. That can lead to any number of problems down the line. Like all VCL windows, the frame's window needs to belong to the main, VCL thread.
Even if you ensure that the frame's handle is created in the main thread before you direct messages to it (such as by calling HandleNeeded
in the main thread), there's still a chance that reading the frame's Handle
property will cause problems. This is because a VCL control might re-create its window. Then, once again, reading the Handle
property may trigger creation of the frame's window in the wrong thread.
The safe technique is for the frame to to call AllocateHWnd
to create a dedicated message-only window. Do that in the frame's constructor so it's guaranteed to happen in the main thread, and then post messages there. When you create the window, you'll provide a callback method that will be called any time that window receives a message. That callback method should belong to the frame control so that it has access to all the fields and methods of the frame it's associated with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With