0

I'm trying to diagnose why my app is freezing up and android is displaying a message that app is not responding. For an unknown reason, messages that should show in logcat output do not when this happens.

I'm looking at using https://github.com/nwestfall/Xamarin.ANRWatchDog to find out what is going on in my app if it becomes non-responsive. The problem is, I don't see anything in call stacks from a c#/managed thread perspective.

All information I've been able to find doesn't work with c#/Xamarin/Android and/or is target the development for desktop/server development. Attempting to get a list of threads gives me a list, but all entries in the list are null. Even if I can a list of the actual threads, how do I get the call stack for each thread?

var threads = Process.GetCurrentProcess().Threads;

Is there a way to get the current stack trace for all managed threads in a Xamarin/Android app?

Ken K
  • 799
  • 3
  • 9
  • 18

2 Answers2

0

System.Diagnostics.StackTrace() for the current thread, however you probably don't care about that.

Here's a way to get other threads and get their stack traces: How to get non-current thread's stacktrace?

If that doesn't work, you can certainly use a method I've used successfully in winforms, a long time ago. Here's the strategy:

  • ensure all your worker threads have a top-level try/catch with logging you can access
  • Abort the worker threads and look for the abort exceptions in the logs!

Sounds simple, but takes you straight to a crash. Still you have to get the threads to abort them, see the threadsampler.Start method first few lines in the S/O link above.

If your UI is responsive you can hide this function in an easter-egg activated devtools menu or have a debug menu activated in your configs (you'll want than when your UI apps get non trivial anyway!)

Unfortunately since it's locking up, you'll just have to start a background thread to run this functionality, you could have it ping the UI every second or 20, and abort threads if it locks. Strategy would be to invoke a 'dummy function' on the UI thread: https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/appmodel/main-thread and wait for it to come back, e.g., InvokeOnMainThreadAsync, it should do that in 5sec or less otherwise you take action. Apply a timeout waiting for it: Asynchronously wait for Task<T> to complete with timeout.

Make sure to turn this off in prod!!! Or optionally, activate via switch you can direct users to turn on.

This is the pattern we used in the field for our app, years and years ago.

Full saga: How do I get the GUI thread of winform?

A newer version of our app does all the work on a background thread and the user gets a chance to cancel if it takes more than 10 sec. However that requires the use of an abstracted UI and the team created a variation on MVVM. Useful as it allows us to deploy a thick client and web app with all the same code - including UI code. Probably not worth the effort for any other apps, and if I had to do that over I'd use javascript for a web app and deploy it to desktop in electron and mobile via cordova, react etc. Oh well.

FastAl
  • 6,194
  • 2
  • 36
  • 60
0

You're probably beyond this (apologies in advance) but there is the Debug\Windows\Threads tab and if I hang a named thread deliberately in my Xamarin Android app:

new Thread(hangMe) { Name = "HangMe" }.Start();
void hangMe()
{
    while(true)
    {
        Thread.Sleep(500);
    }
}

If execution is paused by going to the VS main menu Debug\Break All then there may be some useful call stack info there in the Threads tab.

threads tab

I understand that things are rarely this simple...

IVSoftware
  • 5,732
  • 2
  • 12
  • 23