What is Device.BeginInvokeOnMainThread for?

前端 未结 3 1472
無奈伤痛
無奈伤痛 2021-02-01 16:26

I would like someone to explain to me what is Device.BeginInvokeOnMainThread and what is it for?

And also some examples of cases where it\'s used.

3条回答
  •  既然无缘
    2021-02-01 16:44

    The simple answer is: Background thread cannot modify UI elements because most UI operations in iOS and Android are not thread-safe; therefore, you need to invoke UI thread to execute the code that modifies UI such MyLabel.Text="New Text".

    The detailed answer can be found in Xamarin document:

    For iOS:

    IOSPlatformServices.BeginInvokeOnMainThread() 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/

    You use this method from a thread to invoke the code in the specified object that is exposed with the specified selector in the UI thread. This is required for most operations that affect UIKit or AppKit as neither one of those APIs is thread safe.

    The code is executed when the main thread goes back to its main loop for processing events.

    For Android:

    Many People think on Xamarin.Android BeginInvokeOnMainThread() method use 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 Xamarin.Android BeginInvokeOnMainThread() method can be found in 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, you action code is not executed immediately by Handler.Post(action). It is added to the Looper's message queue, and is handled when the UI thread's scheduled to handle its message.

提交回复
热议问题