Xamarin:如何在UI线程上执行长时间运行的操作时让UI重绘(不使用async / await)

时间:2018-11-03 11:46:08

标签: android multithreading xamarin .net-standard ui-thread

由于种种原因,我被迫在xamarin表单(NetStandard)应用程序的UI线程上执行长时间运行的操作。在此操作期间,我想更新UI以向用户提供有关进度的反馈。我可以对UI进行更改,但是UI无法重绘,因为我无法通过使用await / async将指令指针返回到OS。

有什么方法可以在不使用async / await的情况下处理UI线程上的消息。在旧的Win32时代,我认为Translate / DispatchMessage可以用于使消息泵在长时间运行的操作中保持运行,这与我所需要的类似。

背景:我有一个由在我的UI线程上运行的android操作系统定义和调用的接口。重要的是,我们要从此服务返回此长时间运行的结果。因为该接口未定义为异步,所以我无法使用await让IP返回到OS。如果我这样做了,该函数将立即返回(不获取结果)并继续执行(即,它将失败)。我无法改变这些情况。

// The following class is called directly by the AndroidOS
class CloudHostCardService : HostApduService
{
    // The following method is called by the AndroidOS on the UI thread
    public override byte[] ProcessCommandApdu(byte[] commandApdu, Bundle extras)
    {
        ViewModels.MainPageViewModel.SetStatus("Processing Cmd");  // <-- updates UI
        return processor.ProcessCommand(commandApdu); // <-- Long running operation
    }
}

还有其他方法可以触发重绘吗(在Win32中为泵浦消息)?

1 个答案:

答案 0 :(得分:1)

HostApduService允许您从null返回ProcessCommandApdu,然后稍后使用SendResponseApdu提供ResponseApdu

  

此方法在您的应用程序的主线程上运行。如果您不能立即返回响应APDU,请返回null并稍后使用sendResponseApdu(byte [])方法。

示例:

public class SampleHostApduService : HostApduService
{
    public override void OnDeactivated([GeneratedEnum] DeactivationReason reason)
    {
    }

    public override byte[] ProcessCommandApdu(byte[] commandApdu, Bundle extras)
    {
        // Update your UI via your viewmodel.

        // Fire and forget
        Task.Run(() => {
            this.SendResponseApdu(processor.ProcessCommand(commandApdu));
         });

        // Return null as we handle this using SendResponseApdu
        return null;
    }
}