ewong 3 Posted March 25, 2021 Hi, I have an application which goes through a dataset (a 13k+ entry table) and grabs info and adds it into a dictionary for further use. Due to the length of the table, I had also created an extra form which is basically just a progress bar. When I run the app, the progress bar's position increases. The problem is when I click on something else within the form. The application immediately hangs (Application Not Responding). The application is still running though. After some time, the progress form closes and the data is displayed. I had thought it was a painting issue; but even adding progressform.repaint to the end of the (while not dataset1.eof do) loop, the application hangs. Is there a way to find out what part of the code is hanging or why it's hanging? Thanks Ed Share this post Link to post
Dalija Prasnikar 1396 Posted March 25, 2021 Yes, there is. But without code it is impossible to say for sure. I am guessing that you are doing all that in main thread. Share this post Link to post
Fr0sT.Brutal 900 Posted March 25, 2021 Simple way is to call Application.ProcessMessages from time to time Share this post Link to post
ewong 3 Posted March 25, 2021 57 minutes ago, Dalija Prasnikar said: Yes, there is. But without code it is impossible to say for sure. I am guessing that you are doing all that in main thread. That I believe I am since I'm not using threads or anything. I think I'll try using threads and see how things go. Thanks for the idea! Edmund Share this post Link to post
ewong 3 Posted March 25, 2021 23 minutes ago, Fr0sT.Brutal said: Simple way is to call Application.ProcessMessages from time to time Thanks for that suggestion. I'll keep that in mind for the smaller apps. Edmund Share this post Link to post
Dalija Prasnikar 1396 Posted March 25, 2021 20 minutes ago, Fr0sT.Brutal said: Simple way is to call Application.ProcessMessages from time to time This is bad idea. First, Application.ProcessMessages has some global side effects that can bite you in behind when you least expect them. Next, depending on the code, it is possible that some pieces still take too long to keep UI fully responsive. Using background threads for simple operations is not rocket science and at the end when you take all pros and cons it is not more complicated than using Application.ProcessMessages. 6 1 Share this post Link to post
KodeZwerg 54 Posted March 25, 2021 Do not try update ProgressBar position for every single entry, let it update in steps. ProcessMessages is really a bad Idea! Share this post Link to post
Guest Posted March 25, 2021 Am i wrong, but i seem to remember that the progress bar actually calls Application.ProcessMessages. IMHO that could be your problem. Messages starts to pile up because of something and then when that is finished all those messages gets processed and it looks like a "release". Anyways, show us the code. You could do an MVP using a TClientDataSet perhaps. Share this post Link to post
Attila Kovacs 629 Posted March 25, 2021 (edited) poor man's responsive GUI var FOldMessageEvent: TMessageEvent; FOldMessageEvent := Application.OnMessage; Application.OnMessage := MyOnMessage; try // Do your stuff here and call repetitively Application.ProcessMessages; finally Application.OnMessage := FOldMessageEvent; end; procedure TfrmXY.MyOnMessage(var Msg: TMsg; var Handled: boolean); begin if (Msg.hwnd = btnStart.Handle) and (Msg.Message = WM_MOUSELEAVE) then else if Msg.hwnd = btnAbort.Handle then // if you have an abort button else case Msg.Message of WM_PAINT, WM_TIMER: // handle messages ; else Handled := True; end; end; Edited March 25, 2021 by Attila Kovacs Share this post Link to post
David Heffernan 2345 Posted March 25, 2021 5 hours ago, ewong said: Is there a way to find out what part of the code is hanging or why it's hanging? Run in the debugger. When it hangs, use Run | Program pause to pause execution. Look at the thread window, and double click the main thread since I guess that is the thread which is hung. Look at the call stack window which will tell you what the thread is doing that is not completing. 3 Share this post Link to post
Fr0sT.Brutal 900 Posted March 25, 2021 2 hours ago, Dalija Prasnikar said: This is bad idea. First, Application.ProcessMessages has some global side effects that can bite you in behind when you least expect them. Next, depending on the code, it is possible that some pieces still take too long to keep UI fully responsive. Using background threads for simple operations is not rocket science and at the end when you take all pros and cons it is not more complicated than using Application.ProcessMessages. This is simple and good enough idea for the app described. Side effects are insignificant in single-threaded app (possibility of user input during processing could be easily blocked). Using bg threads for DB actions is getting a little closer to rocket science than App.PrMsg and could seem an overkill for simple app or junior dev. Share this post Link to post
Dalija Prasnikar 1396 Posted March 25, 2021 23 minutes ago, David Heffernan said: Run in the debugger. When it hangs, use Run | Program pause to pause execution. Look at the thread window, and double click the main thread since I guess that is the thread which is hung. Look at the call stack window which will tell you what the thread is doing that is not completing. It seems that everything is running in main thread... so nothing really hands besides application UI. Share this post Link to post
Pat Foley 51 Posted March 25, 2021 Quote When I run the app, the progress bar's position increases. The problem is when I click on something else within the form. The application immediately hangs (Application Not Responding). The application is still running though. After some time, the progress form closes and the data is displayed. Disable the controls When data is loaded have future event enable controls. Rather than a progress bar have windows 10 olympic ring showing until future event happens. Share this post Link to post
Anders Melander 1783 Posted March 25, 2021 2 hours ago, Attila Kovacs said: poor man's responsive GUI var FOldMessageEvent: TMessageEvent; FOldMessageEvent := Application.OnMessage; Application.OnMessage := MyOnMessage; try // Do your stuff here finally Application.OnMessage := FOldMessageEvent; end; I don't think you understand how the message queue works... How are messages supposed to arrive through Application.OnMessage if the message queue isn't being pumped? And if it is being pumped then your code is unnecessary because the messages are already being dispatched and processed. In short: Your code does nothing that isn't already being done. 1 Share this post Link to post
Attila Kovacs 629 Posted March 25, 2021 (edited) @Anders Melander Ahum, there was a line missing, the forum is glitching today;) Edited March 25, 2021 by Attila Kovacs Share this post Link to post
Guest Posted March 25, 2021 I, on the other hand, am wondering how things are going for the OP. Did you solve the problem @ewong? Share this post Link to post
Anders Melander 1783 Posted March 25, 2021 3 hours ago, Dany Marmur said: Am i wrong, but i seem to remember that the progress bar actually calls Application.ProcessMessages. Yes. You are wrong. It processes WM_PAINT messages (which is why it's updating) but leave everything else alone. Share this post Link to post
Anders Melander 1783 Posted March 25, 2021 8 hours ago, ewong said: When I run the app, the progress bar's position increases. The problem is when I click on something else within the form. The application immediately hangs (Application Not Responding). The application is still running though. After some time, the progress form closes and the data is displayed. I had thought it was a painting issue; but even adding progressform.repaint to the end of the (while not dataset1.eof do) loop, the application hangs. First of all the application isn't hanging. It's just not processing messages while it's working. When you click on the form Windows detects that the application hasn't pumped the message queue for a while and assumes this is because the application is stuck in an endless loop somewhere. In your case that's a wrong conclusion because eventually your task finishes and everything is good again. The simple work around is to pump the message queue inside your loop - just don't use Application.ProcessMessages. I believe have previously posted some code here that can be used inside a loop to allow the user to interact with a progress dialog (e.g. move it, push an abort button, etc.) without the pitfalls of Application.ProcessMessages but if you can't find it you can at least pump the queue for WM_NULL messages. I think these are what Windows use to detect a hung application: var Msg: TMessage; while PeekMessage(0, Msg, WM_NULL, WM_NULL, PM_REMOVE) do begin if (Msg.message = WM_QUIT) then PostQuitMessage(Msg.wParam); end; 8 hours ago, ewong said: Is there a way to find out what part of the code is hanging or why it's hanging? If you can reproduce while running in the debugger then just press the Pause button in the debugger and examine the call stack. At run time you can use something like madExcept's freeze detection. It uses the same technique as Windows to detect a hung application and produces a nice call stack when it happens (after prompting the user). Share this post Link to post
Fr0sT.Brutal 900 Posted March 25, 2021 11 hours ago, ewong said: I have an application which goes through a dataset (a 13k+ entry table) and grabs info and adds it into a dictionary for further use. Due to the length of the table, I had also created an extra form which is basically just a progress bar. Isn't it classic block while not DS.Eof do begin ..copy values... FormProgress.PrBar.Stepit; DS.Next; end; ? If so, there's nothing that hangs in your app. Share this post Link to post
Attila Kovacs 629 Posted March 25, 2021 @Dalija Prasnikar Could you explain the difference between "putting a db task into a thread" (thread) vs. "application.processmessages" regarding to the GUI? Share this post Link to post
Guest Posted March 25, 2021 (edited) why all stop on main thread???? It's quite simple!!! remember: a Form always is onto a looping infinite... look on sources, where, the msg is 'catch', and executed... but the looping still been executed until close a form.... for that, ProcessMessage exist, basically. i remember when I used Clipper summer85 sorry my english hug Edited March 25, 2021 by Guest Share this post Link to post
Attila Kovacs 629 Posted March 25, 2021 4 minutes ago, emailx45 said: why all stop on main thread???? application repeat db-task while not dataset.eof do begin // main loop blocked dataset.next; end; form2.showmodal -> modal form repeat Application.ProcessMessages; <- modal form workaround, bites as hell until ModalResult <> 0 Application.ProcessMessages; until terminate Share this post Link to post
Guest Posted March 25, 2021 (edited) I didnt a question! 😁 I showed a fact! hmmmmm... it's so hard somebody "understand" hug Edited March 25, 2021 by Guest Share this post Link to post
Attila Kovacs 629 Posted March 25, 2021 (edited) well, you have to learn foreign languages then, or look for a native forum, you see me? friend 🙂 Edited March 25, 2021 by Attila Kovacs Share this post Link to post