How to handle exceptions in a non-UI thread code?

mshwfmshwf EGMember ✭✭✭

I ran into two threading-related issues, where an exception is swallowed:
1. The page is not navigated to after the landing page, and to find out the problem I had to debug into every line of code (F11) until I reached the code that has the error (null reference) after this line, nothing happens, and the page isn't navigated to.

For the second issue: I had to run the entire page initialization in the main thread, using: Device.BeginInvokeOnMainThread when I realized that the exception is being swallowed when not running in the main thread.

to make sure of this conclusion I wrote code in the view model in a test project, that raises null reference exception, but it did raise exception! (! because "isn't view model code a non-UI related work?").
so it seems there is a random switching between a UI thread and other threads.
so how can I handle these exceptions so I don't spend hours debugging and hating on myself and my work?

Answers

  • JarvanJarvan Member, Xamarin Team Xamurai
    edited January 20

    I wrote code in the view model in a test project, that raises null reference exception, but it did raise exception!

    Updating UI operations should be in main UI thread. Does the view model class have a command to change the views? Could you post the related code to reproduce the issue?

    How to handle exceptions in a non-UI thread code

    Try to detect the AppDomain.CurrentDomain.UnhandledException event to catch the exceptions.
    Check the link:
    https://forums.xamarin.com/discussion/58002/what-is-the-preferred-way-to-catch-all-unhandled-exceptions-on-xamarin-forms

  • NMackayNMackay GBInsider, University mod

    Xamarin Essentials is also really useful for this

    https://docs.microsoft.com/en-us/xamarin/essentials/main-thread

  • NMackayNMackay GBInsider, University mod

    And of course the interfaces if you mock everything like those of us who have to get 90% code coverage for a PR!

    https://www.nuget.org/packages/Xamarin.Essentials.Interfaces/

  • mshwfmshwf EGMember ✭✭✭
    edited January 21

    @Jarvan said:
    Updating UI operations should be in main UI thread. Does the view model class have a command to change the views? Could you post the related code to reproduce the issue?

    Actually it was a command but isn't bound to a view:

    public ICommand Init => new Command(() => Debug.Print(Person.Name)); //Person is null
    neither Init nor Person are bound to views.
    I call it from the constructor:
    Init?.Execute(null);

    But in the main project, it was calling a method on a bindable property (in a custom control) that is null, and even this is strange, because it's a first-class UI citizen (isn't it? it's a ContentView control!). And to fix it, I had to initialize the bound property in the view model.

    I'm soooo confused, the command in the view model which is not bound to any view threw an exception, but the bindable property in a custom view didn't, they're taking each others' role in my understanding!!

  • mshwfmshwf EGMember ✭✭✭

    Also is it good practice to run every suspicious code in the main thread to stay safe?

  • JarvanJarvan Member, Xamarin Team Xamurai

    The exception occured because the Person project may not be initialized in the model class.

    but the bindable property in a custom view didn't

    They are not the same. If you've set binding to a model class, but not set a value to the binding project, the property will use the default value, such as '0' for int , null for string.

  • mshwfmshwf EGMember ✭✭✭

    @Jarvan said:
    The exception occured because the Person project may not be initialized in the model class.

    Yes, I set it to null, to see if the exception is caught or not, this is my problem, not "why the exception is occurred ?"

    They are not the same. If you've set binding to a model class, but not set a value to the binding project, the property will use the default value, such as '0' for int , null for string.

  • mshwfmshwf EGMember ✭✭✭

    @NMackay said:
    Xamarin Essentials is also really useful for this

    https://docs.microsoft.com/en-us/xamarin/essentials/main-thread

    I don't see much difference than the Xamarin.forms Device.BeginInvokeOnMainThread, also is it good practice to run every suspicious code (which is almost any code) in the main thread to stay safe?

  • NMackayNMackay GBInsider, University mod

    @mshwf said:

    @NMackay said:
    Xamarin Essentials is also really useful for this

    https://docs.microsoft.com/en-us/xamarin/essentials/main-thread

    I don't see much difference than the Xamarin.forms Device.BeginInvokeOnMainThread, also is it good practice to run every suspicious code (which is almost any code) in the main thread to stay safe?

    What do you mean by suspicious code? it's up to you to determine what runs of the UI thread and on, if there's a suspicion you can't guarantee where the thread running the code ConfigureAwait(false) - for example then you should wrap it in BeginInvoke, if there's all the way through your viewmodel though it points at a mess underneath IMHO. The benefit of using essentials is you can use interfaces and Mock the services, otherwise you have to use Xamarin Forms Mocks as your viewmodel is littered with UI helper code.

  • mshwfmshwf EGMember ✭✭✭

    By suspicious code I mean any code that could throw an exception, for example a page that failed to be navigated to, I initialize it in the UI thread.

Sign In or Register to comment.