onplatform begininvokeonmainthread xamarin xamarin.forms

onplatform - ¿Por qué usar Device.BeginInvokeOnMainThread() en una aplicación Xamarin?



device.begininvokeonmainthread xamarin android (3)

Mi código se ve así:

public void Init() { if (AS.pti == PTI.UserInput) { AS.runCardTimer = false; } else { AS.runCardTimer = true; Device.BeginInvokeOnMainThread(() => showCards().ContinueWith((arg) => { })); } }

El método Init se llama desde el constructor. ¿Puede alguien explicarme por qué el desarrollador podría haber agregado Device.BeginInvokeOnMainThread () en lugar de simplemente llamar al método showCards?

Además, ¿qué hace el ContinueWith ((arg)) y por qué debería incluirse?


La clase donde este método Init() se podría crear en una cadena de fondo. Supongo que showCards() está actualizando algún tipo de UI. La interfaz de usuario solo se puede actualizar en la interfaz de usuario / hilo principal. Device.BeginInvokeOnMainThread() asegura que el código dentro de la lambda se ejecuta en el hilo principal.

ContinueWith() es un método que se puede encontrar en Task . Si showCards() devuelve una tarea, ContinueWith() se asegura de que la tarea se complete antes de salir de la lambda.


Las acciones de IU se deben realizar en el subproceso UI (nombre diferente para el hilo principal). Si intenta realizar cambios de UI a partir de un hilo no principal, su aplicación se bloqueará. Creo que el desarrollador quería asegurarse de que funcionará según lo previsto.


La respuesta simple es: el hilo de fondo no puede modificar los elementos de la IU porque la mayoría de las operaciones de UI en iOS y Android no son seguros para subprocesos; por lo tanto, debe invocar el hilo de UI para ejecutar el código que modifica la UI, como MyLabel.Text = "New Text".

La respuesta detallada se puede encontrar en el documento de Xamarin:

Para iOS:

El método IOSPlatformServices.BeginInvokeOnMainThread () simplemente llama a 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/

Utiliza este método desde un subproceso para invocar el código en el objeto especificado que está expuesto con el selector especificado en el subproceso de interfaz de usuario. Esto es necesario para la mayoría de las operaciones que afectan a UIKit o AppKit ya que ninguna de esas API es segura para subprocesos.

El código se ejecuta cuando el hilo principal vuelve a su ciclo principal para procesar eventos.

Para Android:

Mucha gente piensa en el método Xamarin.Android BeginInvokeOnMainThread () use Activity.runOnUiThread (), PERO este NO es el caso, y hay una diferencia entre usar runOnUiThread () y 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. } }

La implementación real del método Xamarin.Android BeginInvokeOnMainThread () se puede encontrar en la clase 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) Como puede ver, Handler.Post (acción) no ejecuta inmediatamente el código de acción. Se agrega a la cola de mensajes de Looper y se maneja cuando el hilo de la interfaz de usuario está programado para manejar su mensaje.