2016-05-19 132 views
0

我在点击登录按钮后显示活动指示器,直到将用户重定向到另一个页面,以使他们了解一些进度正在进行。但点击登录按钮后,活动指示灯没有立即显示,几秒钟后显示,更新UI BeginInvokeOnMainThread不立即反映

为什么它是这样的?为了减少延迟只有我把活动的指标......

我的代码:

async void loginButtonGesture_Tapped(object sender, EventArgs e) 
{ 
    Device.BeginInvokeOnMainThread(() => 
        { 
         loadingPanel.IsRunning = true; 
         loadingPanel.IsVisible = true; 
        }); 
} 

回答

0

是否该方法必须异步无效?看起来主线程上的任何特定调度都不需要是异步的。试试看看它是否改变了一切。您也可以尝试在Device.BeginInvokeOnMainThread行和loadingPanel.IsRunning ...行上设置断点,以查看延迟发生的位置。

0

首先,loginButtonGesture_Tapped()事件处理程序由UI线程触发,因此您不需要使用Device.BeginInvokeOnMainThread(),它已经在UI线程中。但是由于您在这里使用了Device.BeginInvokeOnMainThread(),所以延迟的原因是因为在Android上,BeginInvokeOnMainThread()中的代码被添加到MainLooper的消息队列中(您的代码不会立即执行)并在UI线程计划处理其消息。

详细的答案可以Xamarin的文件中找到:

对于iOS:

IOSPlatformServices.BeginInvokeOnMainThread()方法简单地调用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/

您可以使用此方法从线程调用UI线程中指定的选择器公开的指定对象中的代码。 这对大多数影响UIKit或AppKit的操作都是必需的,因为这些API中的任何一个都不是线程安全的。

代码在主线程返回主循环处理事件时执行。

对于安卓

很多人总以为上Xamarin.Android BeginInvokeOnMainThread()方法配合使用Activity.runOnUiThread(),但这种情况并非如此,并没有使用runOnUiThread()和处理器之间的差异.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. 
    } 
} 

实际实现Xamarin.Android BeginInvokeOnMainThread()的方法可以在AndroidPlatformServices.cs类中找到

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) 正如您所看到的,您的操作代码不会立即由Handler.Post(action)执行。它被添加到Looper的消息队列中,并在UI线程计划处理其消息时进行处理。