locked
Implementing IDisposable RRS feed

  • Question

  • User275381 posted

    I have a .NET class that wraps some Xamarin Android objects and implements IDisposable. It's structured as follows:

    public class Wrapper : IDisposable { private readonly FusedLocationProviderClient client; private readonly MyLocationCallback clientLocationCallback;

    public Wrapper(Context context) {
        this.client = LocationServices.GetFusedLocationProviderClient(context);
    }
    
        public virtual void Dispose() {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposing) {
            if (disposing) {
                this.client.RemoveLocationUpdatesAsync(this.clientLocationCallback).ContinueWith((r) => {
    
                }, TaskScheduler.FromCurrentSynchronizationContext());
                this.clientLocationCallback.LocationUpdated -= clientLocationCallback_LocationResult;
            }
        }
    

    }

    I am currently not calling the Dispose() method on the wrapped android objects. I was seeing some weird behavior when I tried to Dispose the wrapped objects in Dispose() of the wrapper. Am I correct on thinking that:

    1) Do not call Dispose() of wrapped native objects unless they are large objects (bitmaps). 2) The Android GC will collect the wrapped native objects separately from the .NET Wrapper (invoked via Mono GC). 3) The current implementation will not leak.

    Wednesday, August 22, 2018 3:22 PM

Answers

  • User368901 posted

    he Android GC will collect the wrapped native objects separately from the .NET Wrapper (invoked via Mono GC).

    Xamarin Android objects have two halfs understood by two VMs:

    1. Managed Peer (collected by Mono)
    2. Native Peer(collected by Android Runtime)

    And between the two peers there is a reference between them. And the java Native peer won't be collected until this reference is broken.

    For detailed explaination, please refer to Cross VM object collections.

    Do not call Dispose() of wrapped native objects unless they are large objects (bitmaps).

    70% yes. recommended way is to release the managed peer first then explicitly call GC.Collect() to prompt a GC to release the Java-side memory. If you want to call dispose of Java.lang.Object, you must be very careful. You can refer to Helping the GC for details.

    The current implementation will not leak.

    Looks ok from the codes snippet.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, August 24, 2018 8:05 AM

All replies

  • User368901 posted

    he Android GC will collect the wrapped native objects separately from the .NET Wrapper (invoked via Mono GC).

    Xamarin Android objects have two halfs understood by two VMs:

    1. Managed Peer (collected by Mono)
    2. Native Peer(collected by Android Runtime)

    And between the two peers there is a reference between them. And the java Native peer won't be collected until this reference is broken.

    For detailed explaination, please refer to Cross VM object collections.

    Do not call Dispose() of wrapped native objects unless they are large objects (bitmaps).

    70% yes. recommended way is to release the managed peer first then explicitly call GC.Collect() to prompt a GC to release the Java-side memory. If you want to call dispose of Java.lang.Object, you must be very careful. You can refer to Helping the GC for details.

    The current implementation will not leak.

    Looks ok from the codes snippet.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, August 24, 2018 8:05 AM
  • User275381 posted

    Thank you so much!

    Friday, August 24, 2018 2:24 PM