Questions about Activity.RunOnUIThread - xamarin.android

RunOnUIThread feels like the UI thread in an Android application is just the UI thread,
Is the same thread that's used for all activities throughout a single application?
If so , do I must use Activity.RunOnUIThread?
Or Is there any alternative?

RunOnUiThread runs code on UI thread (surprise!). if the current thread is UI thread, that code will be executed immediately, otherwise (if the current thread is not the UI thread), the code will be queued in UI thread's event queue.
UI thread is the main thread of execution and most of codes run on it. (actually any code that change UI should run on UI thread)
Do I must use Activity.RunOnUIThread?
You have to use RunOnUIThread when you are in Non-UI thread (e.g: background thread).
Or Is there any alternative?
If you mean is there any other method that force code to run on UI thread, yes, I think you can use Handler for that. (this may helps: Why to use Handlers while runOnUiThread does the same?)
Bonus: Here is my 2 helper methods that related to the question:
public bool IsMainThread
=> Build.VERSION.SdkInt >= BuildVersionCodes.M
? Looper.MainLooper.IsCurrentThread
: Looper.MyLooper() == Looper.MainLooper;
public void RunOnMainThread(Action action)
{
if (IsMainThread) action();
else RunOnUiThread(action);
}

The runonUIthread is used when you run a command (such as a snackbar as an example) from a worker thread. Anything that affects the display should be on the same thread to prevent weird artifacts. And just in case you didn't know, android is multi-threaded. It uses one for UI and if you program it properly, any processing you do is on a different thread. That way your interface always acts butter-smooth.

Is the same thread that's used for all activities throughout a single application?
Threading in Android is simpler then you might think, any application, in general, can have n number of threads, but there is only one UI Thread. The thread on which all UI related changes are made is what is called the UI thread. With RunOnUIThread If the current thread is UI thread, that code will be executed immediately, otherwise (if the current thread is not the UI thread), the code will be queued in UI thread's event queue. In case if you make any changes in your UI and if it is in some background thread like an async-await based Restful Apicall then it won't get reflected as that was not made on the Background thread and hence id not known to the running 'Activity', since RunOnUIThread is only available in an activity context in fragments you will need to use the Activity property to get it and use it.
If so , do I must use Activity.RunOnUIThread? Or Is there any alternative?
It is not always needed, but there are scenarios where you might wanna use it. (As explained above)
For eg: An async method that opens a popup after its done executing will need the RunOnUIThread method otherwise your Pop-Up or alert will never show up because the change was not made on UIThread but an asynchronous background thread.
Similarly, If you have an OnCreate method and you have a requirement to show an Alert as soon as the page opens now if you decide to write this down directly in the OnCreate method there are chances it might not show in that case you run it on UIThread.()

Related

Scheduling execution of blocks in Objective C

I'm creating an application in objective C where I have two threads:
The main thread, which is woken up from sleep and is called into asynchronously by a module above it
The callback block(thread) whose execution is asynchronous and is dependent on an external module "M" sending a notification.
On my main thread, I want to wait for the callback to come in before I start doing my tasks. So, I tried using dispatch_group_enter and dispatch_group_wait(FOREVER) on the main thread while calling into dispatch_group_leave on the callback thread. This ensured that when the main thread is the first to execute, things happen as they are supposed to, i.e the main thread waits for the callback to come in and unblock it before performing its tasks.
However, I'm seeing a race condition where the callback block gets called first sometimes and is stuck on dispatch_group_leave (since at this point the main thread has not called into dispatch_group_enter.
Is there a different GCD construct I can use for this purpose?
The “main thread” is a thread which handles UI, system events, notifications, etc. We never block that thread. Blocking it results in a horrible UX where the app will appear to freeze and your app may even be terminated by the “watch dog” process, which kills apps that it thinks are frozen. In some cases, the app will deadlock.
So, if you really mean “main thread”, then the answer is that you would never “wait” on that thread (or otherwise block it). The pattern is to have your background thread do what it needs, and then dispatch model/UI updates back to the main thread with GCD (or submit your notification and let the main thread process it).
If you want a UX where the user is not allowed to interact with the UI while this background process is underway, you would present something in your UI that makes that clear. A common pattern is a dimming/blurring view that covers the whole view, often with a UIActivityIndicatorView (i.e., a spinner), and when the task dispatched to the background queue is done (or have the notification handler do that), you’d then remove that dimming/blurred view and the spinner and update the UI accordingly.
But you never block the main thread by waiting.

Run a form in a separate thread

Let's say I have a form Foo.
How do I create an instance of that which runs in it's own thread and gets updated even though the main application thread might be busy doing something else? For instance handling blocking network communication or something like that.
I understand the fundamentals and that I need to create a new thread, create the form instance in that thread etc. But then I figure I need an update loop for that thread/window and I'm not at all sure how that should look.
You shouldn't create forms in threads any than your main application thread, because windows message queue is associated only with this main thread.
Think differently: To be sure, that your forms are always updated and responsive, create separate threads for busy work like handling blocking newtork communications and so on, not for forms. In such case, after creating new thread, main form continues to pump messages from it's queue, while function in different thread is doing dirty-work that you need. When the working thread finishes, it can inform main thread about results, using PostMessage() WinAPI function. You should just simply provide handlers for such custom messages in your forms, and they will communicate with working threads seamlessly.
Also, if your "busy work" isn't very complicated, you can even deal without additional threads, by running your work in the form thread, and just calling ProcessMessages() function from time to time, to keep the form updated.

Have data retrieved by separate thread returned to main thread for display in UI

I have an application that has a button and a label. When the button is clicked, an asynchronous separate thread is started that calls a Web Service. Once the Service responds, the thread then passes the data back to a function in the MainViewController in the form of an object. However since that function is getting called by the separate thread, it has no way of displaying that data in the UI (main thread). When I try to assign text to a label or change a picture or do any UI manipulation at all, nothing happens.. All UI objects are NULL objects when the function runs. Does anyone have a suggestion as to how I might be able to get data back into the main thread from the spawned thread?
Thought -
I suppose I could store the object in a global variable, but still need to be able to notify the main thread that there is data to go get and display.
You should really look into Grand Central Dispatch instead of manual threading. If your requirements allow you to use it, it will make your life much simpler when it comes to running things in the background and passing data safely between background threads and the UI thread.

How to avoid a thread freezing when Main Application is Busy

I'm having a bit of a problem. I want to display a progress form that just shows an animation on a when the main application preforms heavy operations.
I've done this in a thread and it works fine when the user isn't preforming any operations. But it just stops when my main application is busy.
I'm not able to put Application.ProcessMessages in between the different lines of code because I'm using 3rdparty components with heavy processing time.
My idea was to create a new process and in the process create a thread that execures the animation. Now that wouldn't stop the thread form executing when the main application performs heavy operations.
But as I see it you can only create a new process if you executes a new program.
Does any one have a solution on how to make a thread continue executing even when the main application is busy?
/Brian
If your worker thread does not have a lower priority than the main thread, you don't use the Synchronize() method, don't call SendMessage() and don't try to acquire any synchronization object that the main GUI thread has already acquired, then your secondary thread should continue to work.
As the VCL isn't thread-safe people do often advise to use Synchronize() to execute code to update VCL controls synchronously in the context of the VCL thread. This however does not work if the VCL thread is itself busy. Your worker thread will block until the main thread continues to process messages.
Your application design is unfortunate, anyway. You should perform all lengthy operations in worker threads, and keep the main thread responsive for user interaction. Even with the fancy animation your app will appear hung to the user since it won't redraw while the VCL thread is busy doing other things and processes no messages. Try to put your lengthy code in worker threads and perform your animation in timer events in the main thread.
Your logic is backward. Your thread should be doing the "heavy work", and passing messages to your main application to update the progress or animation.
If you leave all the "heavy work" in your main application, the other thread won't get enough chances to execute, which means it won't get a chance to update anything. Besides, all access to the GUI (VCL controls) must happen in the application's main thread; the VCL isn't thread-safe. (Neither is Windows itself, when it comes to visual controls.)
If by "Does any one have a solution on how to make a thread continue executing even when the main application is busy?" you mean that main thread is busy you should move the code that is consumming main thread to another other thread. In other words main thread should be responsible for starting and stopping actions and not executing them.
Disclaymer:
Actually I don't know delphy but I think/hope the concepts are quite similar to C++ or C#.

Delphi Thread freeze

I coding a service application that have two threads.
First thread, show a form with label.
Second thread, query ADO.
First thread always freezing with Hourglass cursor and no label caption.
Please help.
If you're trying to show a form from within a thread that is not the main thread, then you will run into strange things like this. The most notable of which is that if the form and label are created in the non-main thread, then you don't have a message loop to process the messages. If the form was created in the main thread, but you're attempting to show it from the non-main thread, then it is likely a dead lock due to how Windows deals with messages and threads.
When a window handle is created it is tied to the thread on which it was created. This means that Windows will ensure that any messages sent to that handle are processed on that thread.
I would strongly suggest you read up on how window messages, message queues, and handles all interact and function in a multi-threaded environment. If not done correctly, you are assured of some very odd and possibly unpredictable behavior.
I would call your condition either a Race, a Deadlock, or some other kind of error like that. As Allen says, if the background thread makes ANY direct access to the VCL controls, without using TThread.Synchronize(myMethod) to invoke the myMethod that touches your VCL foreground, then this alone would cause your trouble.
Post more information, including a sample of your code please.

Resources