DavidJr. 1 Posted November 23, 2022 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
PeterBelow 239 Posted November 23, 2022 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
DavidJr. 1 Posted November 23, 2022 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
PeterBelow 239 Posted November 23, 2022 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
Lajos Juhász 295 Posted November 23, 2022 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
DavidJr. 1 Posted November 23, 2022 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
DavidJr. 1 Posted November 23, 2022 Also I do call CheckSynchronize from the main UI, there is no problem getting information from threads to main UI. Share this post Link to post
FPiette 385 Posted November 23, 2022 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
DavidJr. 1 Posted November 23, 2022 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
Pat Foley 52 Posted November 23, 2022 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
DavidJr. 1 Posted November 23, 2022 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
Pat Foley 52 Posted November 23, 2022 Gamers and workers use various apps to keep windows up. Not sure of safety of something off the web. Share this post Link to post
Remy Lebeau 1436 Posted November 24, 2022 (edited) 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 November 24, 2022 by Remy Lebeau Share this post Link to post
DavidJr. 1 Posted February 13, 2023 On 11/23/2022 at 10:16 PM, Remy Lebeau said: 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). thanks. I resolved that issue, I should have replied sooner. I have long running procedure holding up the UI those same procedures replied on UI values as well. Share this post Link to post
Remy Lebeau 1436 Posted February 13, 2023 43 minutes ago, DavidJr. said: I have long running procedure holding up the UI Definitely not a good design choice. Long-running procedures should be moved to a worker thread. Share this post Link to post
DavidJr. 1 Posted February 14, 2023 15 hours ago, Remy Lebeau said: Definitely not a good design choice. Long-running procedures should be moved to a worker thread. thats exactly what I did. thanks. Share this post Link to post