A VCL/LCL application is per definition event driven. IOW some event happens, and you process that in relative short time, and return to the message/event loop. This keeps everything responsive.
Application.processmessages is a stopgap to do an occasional non-event driven programming, it allows you the run the event loop manually. For relatively simple applications this can be a solution, specially if you only use it in one spot, but it simply doesn't scale.
You can imagine if within a procedure/method that does Application.processmessages the event loops receives some message that calls another procedure/message that calls Application.processmessages. Then you get a kind of recursion (core event loop -> proc1 application.processmessages event loop->proc2.processmessages event loop -> etc). This also means that if you come back from the nested loop-with-nested processmessages to the outer one, that the outer must be prepared that a whole lot has happened during its application.processmessages and update its state accordingly
Many Delphi programmers simply don't understand these kinds of consequences, and randomly throw in some procesmessages "to keep things going". Which is fine, as long as it lasts. But they keep adding more cases, make the application more complex (and thus with heavier event-pressure), and at a certain point it blows up in your face.
If the above situation happens, the bad thing is that it doesn't just blow up, but it is hard to debug/fix/reproduce in such case. (you've painted/programmed yourself into a corner) There are many causes possible, and an shear infinite number of possibilities.
So a single case is fine, but if you rely to much, you really should look at threads. And whatever you do, try to keep an overview and understand what is happening. No technique takes ignorance particularly well.
But threading is the long term solution, but it requires some getting used to. Start with factoring the longest and/or most isolated calculations to threads.