0

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)?

9
  • Are you using Forms or a native Android app? Via Forms, use BeginInvokeOnMainThread Or natively: stackoverflow.com/questions/36619293/… Commented Nov 3, 2018 at 12:32
  • Sorry, maybe the question wasn't clear. I'm already on the main thread, and am forced to complete a long-running operation there. I can manipulate UI elements, but the system won't redraw because I am holding the instruction pointer for that thread Commented Nov 3, 2018 at 15:42
  • Do your "compute" processing on another thread. (As a side note, why can you not add async to the callback method?) Commented Nov 3, 2018 at 15:52
  • I can't do either of those things, because the callback is called by the Android OS (in response to an NFC trigger), and the callback is not defined as async. Commented Nov 3, 2018 at 16:01
  • 1
    You can "just" add async to the method. You should update your question with the code in question, also you can perform a Task.Run in that method, that processes what you need on a background thread and then do a RunOnUiThread to update the ui Commented Nov 3, 2018 at 16:03

1 Answer 1

1

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.

Example:

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; } } 
Sign up to request clarification or add additional context in comments.

3 Comments

oh.my.god. Thanks for the RTFM reminder. I've read the docs so many times I didn't even think to go there for the answer. I'll be testing this out as soon as local opens.
yup works a charm. Thanks a tonne Mr Sushi, hope the hangover gets better
@FrozenKiwi NP, Glad to help 🍣

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.