Reputation: 1513
I am (for reasons) forced to perform a long-running operation on the UI thread of my xamarin forms (NetStandard) application. During this operation, I would like to update the UI to give the user feedback on progress. I can make changes to the UI, but the UI will not redraw as I cannot return the instruction pointer to the OS by using await/async.
Is there any way I can process messages on the UI thread without using async/await. In the old Win32 days I think Translate/DispatchMessage could be used to keep the message pump going in long-running operations, and this is similar to what I need.
Background: I have a interface defined and called by the android OS that runs on my UI thread. It is important that we return the result of this long-running operation from this service. Because the interface is not defined as async I cannot use await to let the IP return to the OS. If I did the function would immediately return (without the results being fetched) and continue executing (ie, it would fail). I can't change these circumstances.
// 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
}
}
Is there any other way to trigger a redraw (pump messages in Win32 speak)?
Upvotes: 0
Views: 771
Reputation: 74209
HostApduService allows you to return null
from ProcessCommandApdu
and then later use SendResponseApdu to supply the ResponseApdu
.
This method is running on the main thread of your application. If you cannot return a response APDU immediately, return null and use the sendResponseApdu(byte[]) method later.
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;
}
}
Upvotes: 1