What is Device.BeginInvokeOnMainThread?

I would like someone to explain to me what Device.BeginInvokeOnMainThread is? And what is it for? examples of cases when they are used.

Thanks.

+8
xamarin xamarin.forms
source share
3 answers

Just add an example.

Imagine you have an async DoAnyWorkAsync method if you call it (as an example) as follows:

  DoAnyWorkAsync().ContinueWith ((arg) => { StatusLabel.Text = "Async operation completed..."; }); 

StatusLabel is the label that you use in XAML.

In the above code, the message on the label will not be displayed after the async operation is completed, since the callback is in a different thread than the user interface thread, and because of this, it cannot change the user interface.

If you update the same code a bit, simply enable the StatusLabel text update in Device.BeginInvokeOnMainThread as follows:

  DoAnyWorkAsync().ContinueWith ((arg) => { Device.BeginInvokeOnMainThread (() => { StatusLabel.Text = "Async operation completed..."; }); }); 

there will be no problems.

Try it yourself by replacing DoAnyWorkAsync() with Task.Delay(2000) .

+3
source share

You can only update the user interface from the main user interface thread. If you use the code in the background thread and you need to update the interface, BeginInvokeOnMainThread() allows you to force your code to run in the main thread, so you can update the interface.

+3
source share

The simple answer: The background thread cannot change the interface elements, because most of the user interface operations in iOS and Android are not thread safe; therefore, you need to call the user interface thread to execute code that modifies the user interface, such as MyLabel.Text = "New Text".

A detailed answer can be found in the Xamarin document:

For iOS:

IOSPlatformServices.BeginInvokeOnMainThread () The method simply calls NSRunLoop.Main.BeginInvokeOnMainThread

 public void BeginInvokeOnMainThread(Action action) { NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke); } 

https://developer.xamarin.com/api/member/Foundation.NSObject.BeginInvokeOnMainThread/p/ObjCRuntime.Selector/Foundation.NSObject/

This method is used from the stream to call code in the specified object, which is displayed with the specified selector in the user interface stream. This is required for most operations that affect UIKit or AppKit, since none of these APIs is thread safe.

Code is executed when the main thread returns to its main loop to handle events.

For Android:

Many people think that the Xamarin.Android BeginInvokeOnMainThread () method uses Activity.runOnUiThread (), BUT this is not the case, and there is a difference between using runOnUiThread () and Handler.Post ():

 public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action);//<-- post message delays action until UI thread is scheduled to handle messages } else { action.run();//<--action is executed immediately if current running thread is UI thread. } } 

The actual implementation of the Xamarin.Android BeginInvokeOnMainThread () method can be found in the AndroidPlatformServices.cs class

 public void BeginInvokeOnMainThread(Action action) { if (s_handler == null || s_handler.Looper != Looper.MainLooper) { s_handler = new Handler(Looper.MainLooper); } s_handler.Post(action); } 

https://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable) As you can see, the action code is not immediately executed by the Handler.Post (action) handler. It is added to the Looper message queue and processed when the user interface thread is scheduled to process its message.

+1
source share

All Articles