I'm rewriting my existing (swift) iOS physical therapy app "On My Nerves" to Xamarin.Forms. It's a timer app to help people with nerve damage (like me!) do their desensitization exercises. You have these "fabrics" (e.g. a feather) where each fabric has an 'x' second countdown. When once fabric's timer reaches 0, a message box appears saying "time's up". The user hits OK and the next fabric starts its countdown. Rinse and repeat for all fabrics in the list. Here's a video showing the workflow. Trust me on the UX in the video.
Here's my sample app code demonstrating this behavior.
The DoSomethingForNow
method (forgive my naming strategy) is the callback from the NotificationService (see line 65 - not enough SO rep points for direct link) that is created when the timer starts, in case the app gets the background.
The specific call that is not working on Release mode on Device is at line 115
Device.BeginInvokeOnMainThread(
async () => await ShowAlertAndWaitForUser(currentFabricCount));
The async () => await ShowAlertAndWaitForUser(currentFabricCount))
works as expected in Debug and Release configuration on iOS Simulator, and in Debug configuration on the device.
However, the message box indicating time is up does not appear in Release config on the physical device. I cannot figure out why Device.BeginInvokeOnMainThread()
doesn't work in Release config on device. What is going on?
Side note re using Device.StartTimer()
The reason why I switched from Device.StartTimer()
to James's FrenchPressTimer solution (see jamesmontemagno/FrenchPressTimer) early on is because I need a way to cancel / stop / whatever a Device.StartTimer()
in case the user needs to pause or stop the countdown on the app.
The Device.StartTimer()
code works great for me on all configurations on both simulator and device and thankfully someone showed me how to cancel a Device.StartTimer (thanks!). If you want to see this working solution, check out saraford/Device-StartTimer-Working-Xamarin on GitHub.
My specific question is why doesn't Device.BeginInvokeOnMainThread()
display a message box when invoked from a notification callback in Release config on a physical device.
I've also tried the different linker combinations. No effect.
Here's an answer that will work, but as @JamesMallon has mentioned, don't use it:
Device.BeginInvokeOnMainThread(ShowAlertAndWaitForUser(currentFabricCount).Result);
Your issue is very common in situations where the code is not run in the Main/UI thread. It seems that you begin the invoke on the main thread but the UI thread doesn't actually read the line, and another thread instead is performing the actions you require. And that's also why it works some times and doesn't work during other times.
So instead of performing the whole ShowAlertAndWaitForUser()
on the UI thread, try to instead run only the DisplayAlert
function on that thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With