Incus J 10 Posted February 6, 2019 In Delphi VCL I can use application.processmessages to process any queued messages, including pending events such as mouse clicks. Firemonkey also has application.processmessages - but its behaviour seems different, in that it doesn't process queued mouse clicks on buttons. This means that I am unable to check to see whether a Cancel button has been clicked part way through an operation. Is this correct? (Delphi FMX Tokyo 10.2.3) Share this post Link to post
Sherlock 663 Posted February 6, 2019 The problem there might be, that FMX-Buttons are not Windows Buttons, and therefore don't rely on Windows messages. At least, that's what I remember about FMX. Share this post Link to post
Guest Posted February 6, 2019 Someone said that FMX has message processing. Since FMX is multi-platform this must mean that FMX simulates windows message processing. I should rephrase this to a question; does FMX use actual windows message processing on Windows and simulates them/use a different approach on other platforms? If it is not a 100% simulation on all platforms i suspect using message processing in FMX code will make the code behave differently on different platforms? Share this post Link to post
Dave Nottage 557 Posted February 6, 2019 ProcessMessages will not work as you may expect in FMX, and definitely not on Android. I suggest avoiding ProcessMessages entirely; then it won't matter which framework or platform you're using. It may be better to describe why you think it's necessary to use it (preferably with example code), because it's likely there are other ways to solve it. 1 Share this post Link to post
Leif Uneus 43 Posted February 6, 2019 (edited) @Incus J Using Application.ProcessMessages is not the correct way to test if the GUI is updated in a lengthy process. Put your lengthy operation in a separate thread and add a possibility to cancel it if the GUI detects such a request. Application.ProcessMessages can lead to many hard to find anomalies and program failures. Edited February 7, 2019 by Leif Uneus Spelling 3 Share this post Link to post
Incus J 10 Posted February 8, 2019 Thank you for all the responses. It makes sense that FMX might have its own queue for UI controls. So Application.ProcessMessages may not be viable, and there may be a much better way to solve this, somehow. If I get a little more specific, would that help point to an alternative approach? Here's what I have so far: 1. User clicks "Go" 2. UI is disabled 3. Lots of photos are processed (lengthy operation) 4. UI is enabled again Apart from a Cancel button, the UI is intentionally disabled to user input during the lengthy operation. However several UI controls are regularly updated to indicate progress (a progress bar, image list, image view). This is all working OK right now. Since the UI is disabled, re-entrancy isn't an issue. The only thing lacking is a way to let the user cancel the lengthy operation part way through if they wish. I'd like to keep it simple. Is there a simple robust way to achieve a Cancel button? Threads: This scares me. Everything I've read on Delphi tasks and threads in forum post suggests they can lead to really hard to find program failures, and the library perhaps not yet robust. I've developed commercial software in Delphi for 20 years, but I don't feel ready for threads (or maybe the threading library isn't ready for me?). At the moment my software is working. Is there a safe, reliable approach to creating a Cancel button that doesn't give me the option to shoot myself, or my users, in the foot? Share this post Link to post
Sherlock 663 Posted February 8, 2019 1 hour ago, Incus J said: Threads: This scares me. Everything I've read on Delphi tasks and threads in forum post suggests they can lead to really hard to find program failures, and the library perhaps not yet robust. I've developed commercial software in Delphi for 20 years, but I don't feel ready for threads (or maybe the threading library isn't ready for me?). Don't be scared. Actually this is a prime example use case for threads. Just follow the tutorials to get a feeling (http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_the_Parallel_Programming_Library) and then dive right in. You may also want to check out the answers to this SO question: https://stackoverflow.com/questions/44080089/how-to-stop-a-running-ttask-thread-safe For a slightly different approach consider the classic http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread. And then of course there is always the OmniThread library, which I have not yet played with so far, but I hear only good things. Share this post Link to post
Remy Lebeau 1396 Posted February 9, 2019 14 hours ago, Incus J said: Threads: This scares me. Everything I've read on Delphi tasks and threads in forum post suggests they can lead to really hard to find program failures, and the library perhaps not yet robust. I've developed commercial software in Delphi for 20 years, but I don't feel ready for threads (or maybe the threading library isn't ready for me?). There is nothing wrong with using threads in general, you just have to understand WHEN and HOW to use them effectively. You can't write really high performant software without them. Especially on mobile platforms. I've been writing commercial software for 20 years as well, and have written many multi-threaded applications, just using Delphi's 'TThread' class. I don't use a version that has Embarcadero's "Parallel Processing Library" available (I would never trust it anyway, it has had too many bugs over the years!), and I don't use 3rd party threading libraries, like OmniThreadLibrary, etc (not that there is anything wrong with them, I just never got into them). 1 Share this post Link to post
Incus J 10 Posted February 27, 2019 Thank you everyone for the encouragement and advice. I've made an initial attempt using the TThread class as a starting point - with some success, in that the Cancel button now works. To verify the main thread remains responsive I placed a spinning TAniIndicator on the form. It does spin during the lengthy image processing, however it pauses intermittently a couple of times during the processing of each image, which suggests something is still blocking the main thread? Question: Apart from updating the UI, is there anything else that typically requires a Synchronize? For example my thread contains file operations - should they be Synchronized too? I'm also encountering possible intermittent failure of CreateBitmapFromFile - which works perfectly when I run all my code on the main thread. So I'm making progress, but would welcome further pointers. Share this post Link to post
Микола Петрівський 10 Posted February 27, 2019 1 hour ago, Incus J said: Thank you everyone for the encouragement and advice. I've made an initial attempt using the TThread class as a starting point - with some success, in that the Cancel button now works. To verify the main thread remains responsive I placed a spinning TAniIndicator on the form. It does spin during the lengthy image processing, however it pauses intermittently a couple of times during the processing of each image, which suggests something is still blocking the main thread? Question: Apart from updating the UI, is there anything else that typically requires a Synchronize? For example my thread contains file operations - should they be Synchronized too? You should use Synchronize as little as possible, because you are not using threads, when Synchronize is running. Usually you need it only for UI. Share this post Link to post
Remy Lebeau 1396 Posted February 27, 2019 7 hours ago, Incus J said: To verify the main thread remains responsive I placed a spinning TAniIndicator on the form. It does spin during the lengthy image processing, however it pauses intermittently a couple of times during the processing of each image, which suggests something is still blocking the main thread? Then you are probably using Synchronize() ineffectively, or your synced code is doing too much work in the UI thread. Hard to say without seeing your actual code. 7 hours ago, Incus J said: Question: Apart from updating the UI, is there anything else that typically requires a Synchronize? For example my thread contains file operations - should they be Synchronized too? ANYTHING that must be serialized with the main thread needs to be synced. That is USUALLY only the UI, but there may be other things, too. Again, it really depends on your particular code. File I/O is not one of them. Though, if you have multiple threads accessing the same file, they need to coordinate with each other, not with the main UI thread (unless the main UI thread is one of the threads accessing the file). 7 hours ago, Incus J said: I'm also encountering possible intermittent failure of CreateBitmapFromFile - which works perfectly when I run all my code on the main thread. So I'm making progress, but would welcome further pointers. FMX's TBitmap was not thread-safe prior to 10.2 Tokyo, it could not be used safely outside of the main UI thread. But that was changed in Tokyo, which you say you are using. Which CreateBitmapFromFile() function are you using exactly? I don't see any such function in FMX. Share this post Link to post