Urhosharp after close and open: "Underlying native object was deleted for Handle=...."

Google search produces very little mention of this error or solutions.

I get "System.InvalidOperationException: Underlying native object was deleted for Handle = 123456789012. Object.Method" where Object.Method is either a camera Node (rotation) or a Text object (text change) method in the Urhosharp app.

This only happens every other time I open the app, and only if I close it using the back button at the bottom right of the phone (Android). So the first time I open it I get no error. When I close it with the back button and open it again, I get the Exception and the program quits on its own. Then, when I open it again for a third time, the error is not there. But close and open a fourth time, the error reappears, and so on.

But if I close the app manually by using the Recent Apps button on the bottom left of the phone and clicking the X of its window or clicking Close All, then I don't get the error the next time. It even works if after I use the back button to quit, I close its window again in the recent apps list even though it's supposed to already be closed. This leads me to assume that even though I close the app with the back button, it is somehow not totally closed or resources are still tied up until I close it manually with the phone's recent app list.

For what it's worth, the error only started appearing after I implemented remote control of the app through TCP/IP and when I control it that way. The TCP/IP is in the Xamarin.Forms portion, external to Urhosharp, although it does invoke Events that call methods in the Urhosharp app, which is how the exception occurs.

Is there some way I can program the app (C# Visual Studio) to clean itself up when quitting, the same way the phone seems to do when I close it manually through the system? I've tried cleaning up the Nodes in the destructor of the Urho app, but the problem seems to be deeper than that.

I am also at a loss as to how the TCP/IP function is the only thing that causes it. Could it have something to do with the fact that the TCP/IP listener is the only Thread() I'm using in this app? I am however, using Urho.InvokeOnMain() in several places.

Answers

  • PaulNTUPaulNTU USMember ✭✭✭
    edited March 6

    It looks like your losing your handle when you are putting the application to sleep and then starting it again

    Mobile apps dont actually shut down when you click the back button (hence its in the recent applications list, its actually suspended).

    Whats happening is this

    1) Application starts first time and loads from scratch
    2) back button places app to suspended state
    3) Open application now resumes the application from its suspended state, NULL exception and app crashes and dies
    4) Open app again and it loads from scratch (previous instance died so there is nothing in memory)  
        ….  and so on
    
    When closing from the recent apps it actually unloads it and frees up the memory and resets. Next time you open the     app it will load from scratch
    

    To fix this error you need to recreate any handles and initialise Urho components again when the application resumes. If its in a content page then its best to actually do this in the OnAppearing override function for the content page. Its also good practice to clean up any controls manually in the OnDissappearing override function.

    Does that answer your question? I hope it points you in the right direction at least :)

    These links my help for more info

    https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/app-lifecycle
    https://www.tutorialspoint.com/android/android_acitivities.htm

    Paul

  • KronixKronix Member ✭✭
    edited March 8

    Thanks PaulNTU. After running some tests, I have indeed noticed that some things change and other values are reset when using the back button to leave and then coming back. I'll have to dig deeper and research your links and run some tests.

    However, I think this could all be solved by simply answering this question: How do I program the app to completely quit when the back button is pressed, the same as when it is removed from Recent Apps? Then at least I could have a working app, until I find a more elegant solution.

    And another related question is: Is it possible to have the app completely quit and memory cleaned, without removing it from Android's Recent Apps list?

    I also want to point out, even though the back button doesn't completely close the app, it is clearly operating differently than when I press the Home button (bottom center of phone). When I press the Home button, I can come back to the app and nothing is reset. Which begs the question, why does the back button cause the app to only "halfway reset" and what are the rules when it is used and justification for this behavior? It is doing something between pressing the Home button and closing from the Recent Apps list. All this is happening automatically and I don't like it.

  • KronixKronix Member ✭✭
    edited March 8

    Somehow my original reply was deleted while I was working on it without notice. Frustrating.

    Thanks PaulNTU, aftering running some tests I have noticed some values are reset while other objects remain in the same state they were left in when using the Back button to leave and then coming back. I'll have to dig deeper and research your links and run some more tests.

    However, this could simply be solved by answering this question: How do I program the app to completely quit and clear itself from memory when I press the back button, the same as if I removed it from the Recent Apps list?

    I suppose another related question is: Is it possible to make the app completely quit without removing it from the Recent Apps list?

    Furthermore, I have noticed the Home button (bottom center of phone) leaves the app running in the background, and when I come back nothing in the app has been reset. This means the Back button is somehow performing a "halfway reset" between using the Home button and removing from the Recent Apps list. What are the rules for how the Back button quits and what is the justification for it acting this way? This is automatically happening and I don't like it.

  • utekaiutekai USMember ✭✭✭

    Is it possible to make the app completely quit without removing it from the Recent Apps list?

    Catch the OnSleep event and exit when called.

  • KronixKronix Member ✭✭
    edited March 8

    utekai,

    I tried adding

    if (Device.RuntimePlatform == Device.Android)
                    Android.OS.Process.KillProcess (Android.OS.Process.MyPid ());
    

    to the OnSleep event in App.xaml.cs but it doesn't have access to the Android assembly since it isn't the .Android project. I need to add Mono.Android to this but for some reason Visual Studio doesn't make this available to add to projects. It seems only projects created as Android projects get it, and there's no way to manually add it.

    I tried referencing the .Android project but that failed because it would be circular.

    I tried creating an Android class library and referencing that from the root project, but then it says the class library is incompatible with my iOS and UWP projects, presumably because they reference the root project. Is it possible to keep the Android references and/or using statements from being "chained" to the iOS and UWP projects that reference the root project?

    I tried adding

    <Reference Include="Mono.Android" />

    to the root .csproj file and that failed too. The reference shows up in Assemblies in the Solution Explorer but it has a yellow triangle on the icon, gives a warning that it could not locate the assembly, and the "using Android.OS" reference in App.xaml.cs is not recognized.

    How can it be so difficult to access the Android class from the root App.xaml.cs file? I mean, I need it in App.xaml.cs in order to access the OnSleep() event, right?

  • utekaiutekai USMember ✭✭✭
    edited March 9

    I mean, I need it in App.xaml.cs in order to access the OnSleep() event, right?

    Yes, that is one place where the OnSleep event can be handled. But not the only place, depending upon your code structure.

    But still wondering if there aren't other simpler ways. All that's happening is an object is deleted. But you don't know which one yet.

    So the first time I open it I get no error. When I close it with the back button and open it again, I get the Exception and the program quits on its own. Then, when I open it again for a third time, the error is not there. But close and open a fourth time, the error reappears, and so on.

    I propose it would be useful to learn exactly which object is deleted, right now it's only conjecture. Use logging to see the handles of the objects you create and which one specifically is being deleted. You might add additional references to that object to keep it alive and decide that's how you want the program to behave, unless you X-Out of it manually.

    Alternatively, from the OnSleep, you could generate an event similar to what's causing the program to quit on it's own when an exception is generated. For instance, you could create and throw that exception in OnSleep. I'm not recommending that as an operational pattern, but as a step on the way to figuring this out.

    For UWP apps, there's a specific lifecycle that has changed during the past year or so. Understanding the android lifecycle is important to get your android app to behave in all the likely cases users will put it through.

  • KronixKronix Member ✭✭
    edited March 10

    What do you mean X-Out?

    I get the error when I'm assigning to either a camera Node or a text field on the Urho surface. How do you mean add additional references to keep it alive?

    This is all happening in the Urho app, which is in the Urho surface which in turn is a control on the Xamarin.Forms page. Perhaps the Urho surface is somehow resetting when the program goes into the background? I wish this was simple, but apparently I need to do more research.

    BTW, I was able to kill the App by sending a delegate from the Android project that kills the Android App (just has the kill code from my previous post that requires the Mono.Android library) to a new constructor in the root project:

        Action KillApp;
    
        public App(Action Kp)
        {
            InitializeComponent();
            MainPage = new DetailPage();
            KillApp = Kp;
        }
    
        protected override void OnSleep()
        {
            if (Device.RuntimePlatform == Device.Android)
                KillApp();
        }
    

    What's interesting about this, is this is the only way I've found to add Android functionality to the root project without adding the Mono.Android library reference (and Android using statements) to the root project that causes conflicts with other references. I'm wondering if this has been discussed anywhere? I mean, ways to provide cross-functionality between projects that cannot chain conflicting references, even though the functionality from the conflicting references need to be accessed from the same project. Are there other best practices for this and is there a name for this concept that I can Google search?

    What I mean by chain referencing is: Project A is referenced by Project B, and Project B also references Library C. A needs to access functionality in Library D, but Library D has conflicts with Library C. If I add a reference to D from A, it causes conflicts with C, because C is referenced by B which sees the new reference to D in the reference space because B is referencing A. (Is there an official term instead of "reference space"? Like a namespace for chained references.)

    The beautiful thing about the delegate is, it executes the function without the calling project needing the library reference that the function uses.

    The only problem with using the OnSleep event, though, is that it resets the app even if I press the Home key. I wonder how I can prevent that so it only happens on the Back key. I still haven't found an explanation for how or why exactly the Back key functions differently/incompletely when shutting down resources.

  • utekaiutekai USMember ✭✭✭

    What do you mean X-Out?

    You wrote:

    clicking the X of its window

    So that is what is meant by X-Out.

    I get the error when I'm assigning to either a camera Node or a text field on the Urho surface

    I'm proposing that you log each and every ID of each and every object you create from the start of the app. Then generate the error to determine exactly which object has been deleted. It might not be the one you assume at this point. Or it might be.

    I wonder how I can prevent that so it only happens on the Back key

    You have to find a way to capture the key pressed and do a path selection based on that.

    How do you mean add additional references to keep it alive?

    I mean by using code such as:

    node.AddRef();

    This is more advanced, but if you first understand which object is being deleted, and assuming you do and find that you are able to modify the unexpected behavior into expected behavior by experimenting with manual reference management for some small, very small, number of objects, where that small number is 1 or 0.

    You might not be able to control the particular object from being deleted, but first find the object for sure.

  • KronixKronix Member ✭✭

    So can I just use AddRef() on all the objects that are getting deleted (or even suspected getting deleted) to keep them from getting deleted? Then just add ReleaseRef() in the destructor of the containing class? I assume the only danger is not having ReleaseRef() called, since that would result in the memory on the Android device remaining unusable even after the App is killed?

    Is there a built-in class to handle the logging of created/deleted objects? I've got dozens of objects and I assume when the error occurs, some of the objects will be deleted, and others will still exist. I assume the object in the line where the error occurs will already be deleted, so I'm not really following what you're asking me to do. Do you have an example or article explaining this?

    What do you think about the chain referencing I mentioned? I was thinking, would some kind of dependency injection container be used for that purpose? Although I've never seen anybody talk of that problem, I think I saw somewhere dependency containers/injectors used outside of Web APIs that might be relevant, I just can't find the article.

  • utekaiutekai USMember ✭✭✭
    edited March 13

    AddRef() may be helpful and may not. Try and see what happens.

    Urho.IO.Log is a built in logging mechanism.

    You have to set the logging level and then can write out a log statement each time you create an object. But you have to figure out where the log is written and if it is being written. Often I have to use remote debugging to get the log statements into the debug window as no log file is written to the device running the software. Depends upon the platform.

    The log is used in various samples, for instance here and here. There are a lot of informational messages the log will spit out if you've not used it, but you have to set the level lower, say to Debug, to see them.

    Chain/circular referencing ... no comment. Not sure this is the right board. But you could just start out with a project that uses mono already, one of the samples and that would give a common framework others could use to assist you. Right now only you know what you've built.

Sign In or Register to comment.