Jump to content
DavidJr.

Windows VCL application pauses when window is not focused...

Recommended Posts

Hi,

 

On a fairly large sized application with a few threads doing most of the work the UI does have 2 timers for updating fields based on calls to Thread class properties, I get a almost consistent pauses in the UI (ie... progress bar updates,  TRichEdit line adds and TLabel caption updates) unless my mouse pointer is moved over the window.  This is on a PC with two monitors.  Is there something I can call to keep the UI from pausing?   I tried finding other posts that ask this before posting here.  Thanks.

 

 

 

David

Share this post


Link to post
29 minutes ago, DavidJr. said:

Hi,

 

On a fairly large sized application with a few threads doing most of the work the UI does have 2 timers for updating fields based on calls to Thread class properties, I get a almost consistent pauses in the UI (ie... progress bar updates,  TRichEdit line adds and TLabel caption updates) unless my mouse pointer is moved over the window.  This is on a PC with two monitors.  Is there something I can call to keep the UI from pausing?   I tried finding other posts that ask this before posting here.  Thanks.

 

 

 

David

The description sounds as if the UI thread does not process the timer messages in the expected fashion unless other messages are also in the message queue, in this case WM_MOUSEMOVE messages. This is not the normal behaviour of a Windows application. Add some logging to the timer events to check whether the events are triggered at the expected interval (OutputDebugStr should do if you run from the IDE).

Share this post


Link to post

The actions in the timer do work,  but methods running in UI thread are not finishing (writing to fields or increasing progressbar) unless my mouse is in the window.

Share this post


Link to post
1 minute ago, DavidJr. said:

The actions in the timer do work,  but methods running in UI thread are not finishing (writing to fields or increasing progressbar) unless my mouse is in the window.

That cannot be unless you are doing something seriously wrong in you UI updating or your timer intervals are very short, so the UI has no time to repaint properly. We cannot diagnose this without seeing some code...

Share this post


Link to post

Without seeing a code the UI reading from a working thread could be a problem as that must be synchronized. The working thread should post information or synchronize with the UI.

Share this post


Link to post
1 minute ago, Lajos Juhász said:

Without seeing a code the UI reading from a working thread could be a problem as that must be synchronized. The working thread should post information or synchronize with the UI.

yes,  it would be a problem,  but I am not doing that.   I call a property and a "getter" method will return a value,  and that all works fine.  The issue is in the methods that reside in the UI thread that do work.  Not everything is in a separate thread,   but all the heavy work is in separate threads,  but the act of pulling in tmp files is all in the main UI thread and the reason is its a legacy app that I have not the abilty to do a complete re-write.    Now the procedure that is called by a timer event is a big one and so I must disable the timer until the procedure completes,  the procedure does call other methods.   I wished I could share the source  but its big and a lot of unrelated code that works exactly as intended its only the stuff that's called in the UI.  I know its preferred to post source code,  but this code isn't something I own and its against the company policy.

Share this post


Link to post

You probably already know that:

1) you cannot access the GUI from a worker thread.

2) Where the code is has nothing to do with the run context. If a thread call a method of the main form, that method is running in the thread context. And if main form code call a thread method (also thru a getter/setter), the it runs in the context of the main thread.

3) All data access from different contexts (main thread / worker thread) MUST be synchronized using critical section or other similar mechanism.

4) If a thread use Synchronize, then the synchronized method is run by the main thread effectively defeating multi-threading.

 

 

 

Share this post


Link to post
13 minutes ago, FPiette said:

You probably already know that:

1) you cannot access the GUI from a worker thread.

2) Where the code is has nothing to do with the run context. If a thread call a method of the main form, that method is running in the thread context. And if main form code call a thread method (also thru a getter/setter), the it runs in the context of the main thread.

3) All data access from different contexts (main thread / worker thread) MUST be synchronized using critical section or other similar mechanism.

4) If a thread use Synchronize, then the synchronized method is run by the main thread effectively defeating multi-threading.

 

Yes.  The problem isn't occurring from any Synchronize call from a worker thread to the main ui thread.  Outside the worker threads (when they have finished their work), is where the problem is. The long running procedure that called the worker threads then waited for the threads to finish before calling other, methods the first few things after the TTask.Wait(2000) do execute  but then it stalls until I move my mouse back over the window.

 

 

Share this post


Link to post
2 hours ago, DavidJr. said:

Now the procedure that is called by a timer event is a big one and so I must disable the timer until the procedure completes, 

Could you warp that big procedure with if busy exit; busy := True; ...busy := False to keep the timer updating the UI.

 

About 6 weeks ago M$ adjusted the TThread to idle down to once per second...to save energy on blade servers. Not recalling the source of that statement. 

Share this post


Link to post
5 minutes ago, Pat Foley said:

Could you warp that big procedure with if busy exit; busy := True; ...busy := False to keep the timer updating the UI.

 

About 6 weeks ago M$ adjusted the TThread to idle down to once per second...to save energy on blade servers. Not recalling the source of that statement. 

that's an interesting idea.    I want to add that it seems to be message related.   So if I move the mouse outside the window and the procedure finishes the TTask.Wait() then it pauses after a long run...  then I can move the mouse around (without clicking on another window) and it resumes and finishes like its supposed to.   But adding in booleans to allow a triggered set of actions in the Timer handler to maybe create messages is worth a try.   When I did strictly linux/unix programming I never had these issues,  Windows is definitely a complex system.

Share this post


Link to post
8 hours ago, DavidJr. said:

Also I do call CheckSynchronize from the main UI,

You should never have to do that if your main UI thread is running properly.  The main UI message loop already handles requests from TThread.Synchronize() and TThread.[Force]Queue() for you.  The only time you ever need to call CheckSynchronize() manually is if either you are blocking the main UI message loop, or if there is no message loop at all (such as in a console app).

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×