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.
}
}
5条答案
按热度按时间l7mqbcuq1#
再举个例子。
假设您有一个异步方法
DoAnyWorkAsync
,如果您这样调用它(仅作为示例):StatusLabel
是XAML中的标签。一旦异步操作完成,上面的代码就不会在标签中显示消息,因为回调位于与UI线程不同的另一个线程中,因此它无法修改UI。
如果是相同的代码,只需稍微更新一点,将
StatusLabel
文本更新包含在Device.BeginInvokeOnMainThread
中,如下所示:不会有任何问题。
您自己试试,将
DoAnyWorkAsync()
替换为Task.Delay(2000)
。f3temu5u2#
对于iOS:
方法只是调用NSRunLoop. Main.开始调用主线程
https://developer.xamarin.com/api/member/Foundation.NSObject.BeginInvokeOnMainThread/p/ObjCRuntime.Selector/Foundation.NSObject/
您可以从线程使用此方法来调用指定对象中的代码,该对象通过UI线程中的指定选择器公开。大多数影响UIKit或AppKit的操作都需要此方法,因为这两个API都不是线程安全的。
代码在主线程返回到其主循环以处理事件时执行。
对于安卓系统:
很多人认为Xamarin.Android BeginInvokeOnMainThread()方法使用Activity. runOnUiThread(),但事实并非如此,使用runOnUiThread()和Handler.Post()之间存在差异:
Xamarin.Android BeginInvokeOnMainThread()方法的实际实现可以在AndroidPlatformServices.cs类中找到
https://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)如您所见,您的操作代码不会立即由Handler.Post(action)执行,而是添加到Looper的消息队列中,并在UI线程计划处理其消息时进行处理。
ldioqlga3#
您只能从主UI线程更新UI。如果您正在后台线程上运行代码并且需要更新UI,则
BeginInvokeOnMainThread()
允许您强制代码在主线程上运行,以便您可以更新UI。wj8zmpe14#
如上所述,任何UI更新都必须在主线程中发生,否则将发生异常。
尽管Xamarin有一个特殊之处。形式,可以操纵UI元素(例如,创建
Label
并将它们添加到StackLayout
的Children
集合中),只要UI的这一部分与当前显示的UI元素分离,就不会失败。此方法可用于通过创建Xamarin.Forms控件并在内存中设置其子/父关系来提高性能。在单独的线程中关闭屏幕,但是为了将它们附加到显示的容器(例如,分配ContentPage
的Content
属性),您必须在Device.BeginInvokeOnMainThread()
中执行此操作。busg9geu5#
在分析某些情况下UI线程与后台线程的关系时,需要注意以下几点:
BeginInvokeOnMainThread
方法(如docs中所述)仅对调用进行排队,并立即返回给调用方。因此,在这种情况下,UI线程和向UI线程提交了一些工作的后台线程可能并行工作。但是也有
InvokeOnMainThread
,如docs中所述,等待UI线程执行方法,直到action指向的代码完成后才返回,所以在这种情况下,后台线程等待UI线程执行完给定的工作,然后继续执行。