Rafal.B 3 Posted October 23 (edited) Hello everyone, I have a SCADA-style application (FMX). It contains several threads, each of which communicates with a PLC, reads data from it, and enqueues it using TThread.Queue to synchronize with the main thread. Each queue entry represents a change in some value (appearance) of a visual component. A single read may involve 300–600 data points. On the main form, I also have a TTimer that updates the current time in a TLabel every 1000ms. There are also a few buttons on the form. In D12, everything works very well. The form's responsiveness is normal (very good). Unfortunately, something has changed in D13. Visual components updated via TThread.Queue are refreshed correctly, but the time display from TTimer refreshes only every 3–15 seconds. Button response is also similarly delayed. It looks as if the handling of TThread.Queue (on the main thread side) consumes 99.9% of the main thread's time. It seems to be a problem with modifying a large number of components on the screen (at least that’s my impression), but... Let me repeat — in D12 everything worked flawlessly. I have no idea what they changed, but D13 is starting to feel like bad luck 😞 Any suggestions on where to start looking for a solution would be greatly appreciated. I know this is a very general description, but I’m unable to share the source code. Edited October 23 by Rafal.B Share this post Link to post
Rafal.B 3 Posted October 27 I realize this is a rather complex topic. I've determined that the problem is 99% related to graphics display. Running one of the animations (TFloatAnimation) that changes the X position of an element (TPatch) causes the main thread to lock (screen unresponsive). But not always. It's difficult to diagnose. First, I wanted to disable the Display Link Service, but unfortunately, there doesn't seem to be an option. I'm looking for detailed information on the changes to FMX support introduced in D13. Unfortunately, it's hard to find anything useful. Share this post Link to post
Anders Melander 2203 Posted October 27 (edited) I don't use FMX but it sounds like a message flood; Something is causing messages to be posted to the queue and the handling of those messages causes more messages to be posted, etc. Likely at a faster rate than you can process them. WM_TIMER and WM_PAINT are low priority, synthesized messages; They are generated by Windows when there are no other messages in the queue and either the internal timer or invalidate flag has been set. Try to rate-limit your updates somehow. E.g. don't update more than once every 10 milliseconds. If that doesn't help, try lowering the rate (i.e. increase the delay). At some point your WM_TIMER messages should start to be handled at the normal rate. You can also try to disable update of all your items and then enable them one after the other. None of this will solve your problem, but maybe it can give you some data about where to focus. Edited October 27 by Anders Melander Share this post Link to post
Pat Heuvel 2 Posted October 28 Are your visual component updates wrapped in BeginUpdate/EndUpdate? Share this post Link to post
Rafal.B 3 Posted October 28 (edited) 9 hours ago, Anders Melander said: None of this will solve your problem, but maybe it can give you some data about where to focus. 4 hours ago, Pat Heuvel said: Are your visual component updates wrapped in BeginUpdate/EndUpdate? Still general, but with more detail: The program (thread in background) receives 300–600 data items every 100ms. They are sent to a queue (I replaced TThread.Queue with TThreadedQueue to gain more control). On the main thread side, a TTimer (Interval = 50ms) retrieves data from the queue and performs preliminary filtering (unchanged data is discarded). In practice, only 0–15(20) items remain that require component updates. This mostly involves changing the Visible or Text properties, less frequently triggering color (TColorAnimation) or position (TFloatAnimation) animations. And that’s all. There’s not even a need to wrap this in BeginUpdate/EndUpdate. Is that really a lot? During testing, the program was stressed with up to 4000 data items every 100ms. There were no issues with handling that load. Everything ran smoothly and responsively. But that was done in Delphi 12. That’s why I chose to implement this project in that environment. Unfortunately, Delphi 13 flipped the table. From a quick glance, I see that they replaced the previous AniThread with a new "Display Link Service" for handling animations. That’s where I believe the root of my problems lies. I want to report this to QP, but there’s no room there for a sufficiently detailed problem description. Can I include a link to this topic as the problem description? Edited October 28 by Rafal.B Share this post Link to post
Cristian Peța 126 Posted October 28 On 10/23/2025 at 8:47 PM, Rafal.B said: Any suggestions on where to start looking for a solution would be greatly appreciated. Have you tried to use a profiler to see where the bottleneck is? Share this post Link to post
Anders Melander 2203 Posted October 28 24 minutes ago, Rafal.B said: Can I include a link to this topic as the problem description? Sure, but without a minimal reproducible example or a description of exactly where/what the bug is there's not much more to report than "I have a problem". 1 Share this post Link to post
Rafal.B 3 Posted October 28 26 minutes ago, Cristian Peța said: Have you tried to use a profiler to see where the bottleneck is? No, I haven't used it. Which one would you recommend? 17 minutes ago, Anders Melander said: Sure, but without a minimal reproducible example or a description of exactly where/what the bug is there's not much more to report than "I have a problem". That's why I haven't reported it yet 🙂 Share this post Link to post
Cristian Peța 126 Posted October 28 30 minutes ago, Rafal.B said: No, I haven't used it. Which one would you recommend? I would use map2pdb with Intel VTune because I have more experience with. Share this post Link to post
Rafal.B 3 Posted October 28 5 minutes ago, Cristian Peța said: I would use map2pdb with Intel VTune because I have more experience with. Thanks. I'll try. Share this post Link to post
John van de Waeter 7 Posted October 28 Just a guess... do you use the Application.OnIdle event? Share this post Link to post
Rafal.B 3 Posted October 28 32 minutes ago, John van de Waeter said: Just a guess... do you use the Application.OnIdle event? No, I don't use it. Share this post Link to post
Rollo62 639 Posted October 28 (edited) 9 hours ago, Pat Heuvel said: Are your visual component updates wrapped in BeginUpdate/EndUpdate? That would be my first guess too. When using this on the Form or Frame level, those commands should be notified through all child components on that form as well: https://docwiki.embarcadero.com/Libraries/Sydney/en/FMX.Forms.TCommonCustomForm.BeginUpdate Edited October 28 by Rollo62 1 Share this post Link to post
vfbb 301 Posted October 28 In RAD Studio 13.0, animations attempt to link to the screen refresh rate, promoting a smoother animation (implemented in the new FMX.DisplayLink.*.pas units), instead to TTimer-based animations existing in RAD 12 or older. Although there is increased frame processing during animations to promote this fluidity, it is not expected to overload the application. BeginUpdate and EndUpdate might solve this. If you are using the Skia render through GlobalUseSkia := True;, consider adding GlobalUseSkiaRasterWhenAvailable := False; to prioritize GPU rendering on Windows. If none of this solves the problem, I suggest you try creating a simpler project simulating the problem for a bug report to QP. Share this post Link to post
Rafal.B 3 Posted October 28 (edited) Maybe I'm not being clearly understood. I don't see any issue with computer overload. The same application running on D12 uses the same amount of CPU (~5%) and GPU (~30–40%) as when running on D13. Animations that are already running continue to work smoothly. However, buttons and timers placed on the main form stop working. And yet, the running animations still perform smoothly 🙂 Clicking on the screen only causes a 'beep'. I'm not using Skia. In my components, animations are configured via the object inspector, and in the code I only use ...Animation.Enable := True/False; Where exactly should I place BeginUpdate/EndUpdate? I don't quite understand 🙂 I tried this: BeginUpdate; ...Animation.Enable := True; EndUpdate; Unfortunately, it didn't help. I guess I'll have to create something similar just to have something to send to QP. Thanks all for your interest in the topic. Edited October 28 by Rafal.B Share this post Link to post
Anders Melander 2203 Posted October 28 41 minutes ago, Rafal.B said: Clicking on the screen only causes a 'beep'. This is a clue. Under various circumstances, DefWindowProc will emit a beep to indicate an error. I don't think it's really documented what the circumstances are. Examples I know of are clicking on a form that has been disabled and calling DefWindowProc with an error code in one of the message params. See also: https://www.google.com/search?q=DefWindowProc+beep Share this post Link to post
Rafal.B 3 Posted October 29 Interesting fact. The program launched several times (4-5 times) in the IDE64 environment without any problems. Subsequent launches resulted in a known error. Nothing in the configuration had changed in the meantime. It's like magic 🙂 Share this post Link to post
John van de Waeter 7 Posted October 29 No idea if it's related, but: In my app, I have a thread that collects data from a server by TCP. Before starting this thread, I enabled the TAniIndicator When finished, the thread set a flag: new data available In the main thread OnIdle event, I checked for this flag and if set, updated the UI, and at last disabled the AniIndicator This worked okay until (I think) 12.3. In 12.3 it took quite a while (a few seconds) before the OnIdle event fired and my UI was updated. I found that if I did NOT enable the AniIndicator, the OnIdle event fired immediately. Somehow it looked like the AniIndicator 'eated' the OnIdle event. I did not investigate the sourcecode Well, FWIW :) Share this post Link to post
Anders Melander 2203 Posted October 29 37 minutes ago, John van de Waeter said: In 12.3 it took quite a while (a few seconds) before the OnIdle event fired and my UI was updated. You can't expect the OnIdle event to be fired continuously. If it did, your application would consume 100% CPU regardless of it doing anything or not. AFAIR, OnIdle is fired once when the message queue becomes empty. Instead of using OnIdle, what you could have done was to post a message when the work was done, and then handle that message (update the UI, disable the animation, etc.) somewhere. Share this post Link to post
John van de Waeter 7 Posted October 29 15 minutes ago, Anders Melander said: You can't expect the OnIdle event to be fired continuously. If it did, your application would consume 100% CPU regardless of it doing anything or not. AFAIR, OnIdle is fired once when the message queue becomes empty. I know. It's just that it used to work, and suddenly it didn't anymore. What the OP is about. Share this post Link to post
Rafal.B 3 Posted October 29 (edited) I'm trying to create a program that demonstrates the problem, but unfortunately, it's not working out. This might be a serious issue. I'm considering an alternative solution — using the old animation handling method in the new D13. Is that possible? Does this make sense? Perhaps EMB could create a small Old/New Animation switch? 🙄🙂 Edited October 29 by Rafal.B Share this post Link to post
Brian Evans 138 Posted October 30 How much work / value updates is there in each item placed in the queue? If it is only one update you could batch updates to some extent by putting a list of 1 or more value updates in a queue entry. That would reduce queue operations significantly. Share this post Link to post
Rafal.B 3 Posted November 8 Unfortunately, I am unable to create a separate application that exhibits the same issues. For the problems I previously described to occur, the original application must also operate in its natural environment (active TCP/IP connections with several PLCs). Any other attempt fails to produce the desired effect. I am therefore forced to stick with these SCADA applications on Delphi 12, where everything works perfectly. I know this has nothing to do directly with the computer's performance. To simplify, the issue appears as if the message queue is no longer being handled by Application.ProcessMessages. Perhaps a situation will arise that helps narrow down the search area. In the meantime, thank you all for your interest and suggestions. Share this post Link to post
Lars Fosdal 1987 Posted November 9 On 10/28/2025 at 9:13 AM, Rafal.B said: I want to report this to QP, but there’s no room there for a sufficiently detailed problem description. Plenty room. It expands. And, it takes attachments. Also, comments. Share this post Link to post
Rafal.B 3 Posted November 9 3 hours ago, Lars Fosdal said: Plenty room. It expands. And, it takes attachments. Also, comments. I reported it. However, I realize the difficulty in documenting this phenomenon. Animations (FMX) are blocking the application. - RAD Studio Service - Jira Service Management Share this post Link to post