What is the best way to update FMX control without using Apllication.Processmessages method, וn main form.
Apllication.Processmessages call can cause to unwanted asynchrony user events to come in before operation completed.
We have old delphi XE5 in ms windows 10, i tried repaint and invalidate but it not help.
Have the OnClick handler disable the button, start a background thread/task to do the actual work, show the "please wait" message, and then exit the OnClick handler. Do not block the main thread at all. Let it run so it can process UI work normally as needed.
When your background work is finished, have the thread/task notify the main thread, which can then dismiss the "please wait" message and re-enable the button.
DO NOT do the actual work in the OnClick handler itself, and DO NOT call Application.ProcessMessages() at all.
Related
Consider the following case:
Main Thread -----UIView info \ --------------------------------------- / Button Updated ------
\ (Some Event) / (Some Event)
\ /
BG Thread ---------------------Validate UIView info-----Update Button------------------------
On the main thread, a UIView is present
UIView makes a dispatch call is made to a background thread
In the BG Thread, the UIView's info is validated.
BG Thread makes a dispatch call to a UIButton on the main thread to update it.
My question is - notice how there is a gap between UIView info and the UIButton which means that the app could technically be updated during this time. How can I possible stop this gap? Essentially, from the BG thread, block the Main Thread till the call comes back?
You cannot and must never block the main thread. If you do, the interface will freeze and, if the blockage lasts too long, the WatchDog process will kill your app dead before the user's very eyes.
You can give the user a sense that something is going on, and discourage the user from doing anything, by, say, turning off user interaction and putting up a spinner. But in general, yes, multithreading is hard; you must be prepared for the possibility that you will come back onto the main thread when the app has changed state.
Rather than block a main thread, disable user input controls in your view until the validation is complete, then re-enable them.
It would also make sense to add an activity indicator with hidesWhenStopped set to true; it will show the user that there's background work in progress if you start it when the background work starts, and stop it when validation is complete.
If there's ever a chance the background process could hang or take longer, e.g. if it's making a network request, you might show/enable a cancel button and a way to terminate it.
Showing activity indicator and possibly providing a cancel button both require that the main thread keep running, so definitely don't block it!
Your button should not be updated in the background. You should always modify UIKit components on the main thread.
You should also never block the main thread, what you're looking for is the show the user an indication that a background process is active. 'UIActivityIndicatorView' might be a good thing to show the user, you could also disable user interaction on the view to prevent the user from touching anything if it's critical for them to wait until the operation is complete but not recommended.
Yes, you should never block the main thread and update UI only on main thread.
That said - show a spinner / activity indicator while busy on the background.
Think carefully about the UI and e.g. present something so the user can not change something while you are busy with e.g. dialog or popover or something like that.
In practise this often becomes more a question of UX than blocking.
In an application, we have multiple forms. Now we want to refresh a form 'X' when user sees the form 'x' either by restoring it from taskbar or with 'alt+tab'. How to recognize this through event.
The events 'OnActivate','OnShow' get called only once when the form is created. So they are not useful here.
Your claim that the TForm.OnActivate and TForm.OnShow events are fired only once per TForm instance is not true.
The TForm.OnActivate event is fired when a TForm window gains input focus for the first time, and afterwards whenever input focus is transferred to that window from another TForm window, while the app is in the foreground.
Note that there are also TApplication.OnActivate and TApplicationEvents.OnActivate events that are fired when your app comes into the foreground for the first time, and afterwards whenever focus moves to another app and then back to your app.
The TForm.OnShow event is fired when a TForm window becomes visible for the first time, and afterwards whenever that window becomes hidden and then is reshown.
Suppose you include a pascal scripting IDE in your application and a script is created that generates a modal form with a button on it and in the button onclick event, you place a debugger breakpoint.
The result, when that button is pressed, will be a deadlocked program that only task manager can kill.
Obviously you don't want to do that, but it would be difficult to control what end users do.
So I was wondering if there was any way to suspend connected modal forms when the pascalscript debugger breakpoint was hit.?
You cannot suspend window modality. It's not a flag.
Modal window runs its own message pump. Which is many levels up in a call stack from the event handler. You cannot change call stack.
In my application, I have actions/buttons that are linked to queries that load new forms and populate tables with data. I would like to have an animated spinner animate while the queries load.
My current code has by default the TaniIndicator.visible/enabled properties set to false and then when the button is pressed to load the new form, the procedure begins by enabling both of those TaniIndicator properties, however, in my application, the spinner never shows and only is faint to see once the queries are finished and the new form is ready to appear. help ?
Using Delphi xe4, developing an iOS application.
It is because you perform your query on the main thread, and UI updates is blocked while the query is executing. You should start indicator, detach a new background thread or queue, launch task on that thread. Once it is done, switch back to main thread and hide or stop the indicator.
I just coded:
application.processMessages
as the article suggested by #LU RD guides to...
Was no need to create another Thread.
I am using indy 10 and i was wondering how can i implement a progress bar for transfering a file.I tried with onWork events but they are not triggred. Another thing that i find anoying is that the application freezes until the stream is downloaded.
What am i doing wrong ?
Add an IdAntiFreeze component to your form and use it's properties and events to get notified of the progress of the network operations.
You can put the download code into another thread using TThread so that your app doesn't freeze while downloading, and have a procedure that you send to TThread.Synchronize to update the progress bar. Also, for OnWork to be called, you have to call OnWorkBegin first, see http://www.borlandtalk.com/image-vp569607.html