none
Order of unloading classes (and static variables) RRS feed

  • Question

  • I understand that static variables will be garbage collected when the class is unloaded, i.e. AppDomainUnload. I have a few questions:
    1. Is there another case where a static variable can be collected? (other than AppDomainUnload)
    2. Is it possible for the GC to collect a private static variable, if it is not used anywhere in the class (except in the class constructor)?
    3. Can I enforce an order when classes are to be unloaded?

    Thank you.

    • Changed type Guo Surfer Friday, December 5, 2008 10:32 AM OP didn't follow up to provide more information
    • Changed type Guo Surfer Tuesday, January 20, 2009 7:43 AM
    Saturday, November 29, 2008 9:20 AM

All replies

  • 1: No
    2: No
    3: No

    ;-p

    Static fields are essentially top-level objects; they will not get collected. You cannot determine order; hence finalizers etc should never look outside themselves to other references - they should primarily release *unmanaged* resources, for example file handles.

    Marc [C# MVP]
    Saturday, November 29, 2008 11:22 AM
  • Thanks. But what can I do if I must ensure some order? I am using an unmanaged library whose "terminate" methods must be called in a certain order, otherwise an access violation occurs. Is there any way around?
    Saturday, November 29, 2008 11:36 AM
  • Hi Hosam,

    Would you mind providing some code about your issue?
    May be we can postpone the collection.

    Best regards,
    Guo
    Tuesday, December 2, 2008 7:44 AM
  • Hi Hosam,

    We are changing the issue type to “Comment” because you have not followed up with the necessary information. If you have more time to look at the issue and provide more information, please feel free to change the issue type back to “Question” by editing your initial post and changing the radio button at the top of the post editor window. If the issue is resolved, we will appreciate it if you can share the solution so that the answer can be found and used by other community members having similar questions.

    Best regards,
    Guo
    Friday, December 5, 2008 10:32 AM
  • Hi Guo,

    This is a description of the issue, which will be followed by sample code.

    I'm using some MATLAB (C/C++) shared libraries. There is one library that has to be loaded before any other library, and unloaded after all others, called MCL (MATLAB Compiler Library). This library provides two main functions: mclInitializeApplication() and mclTerminateApplication(). The first has to be called before loading any other (compiled) MATLAB library, and the second has to be called after unloading all other libraries. Failure to maintain this order can cause an access violation error.
    (Side note: initializing and uninitializing compiled libraries is done via functions called MyLibInitialize() and MyLibTerminate().)

    So I'm maintaining a class hierarchy of the form below. As you can see, I'm trying to maintain the lifetime of MclWrapper.handle beyond the lifetime of all other MatLibHandles, so that an order is enforced.

    This may not be the best way to do it, but I couldn't think of a better way to achieve my goal.


    public class MatLibHandle : SafeHandle {  
        public delegate bool Initializer();  
        public delegate void Terminator();  
     
        Terminator terminator;  
     
        public MatLibHandle(Initializer init, Terminator term) {  
            this.terminator = term;  
            if (!init())  
                throw new Exception("Could not initialize library");  
        }  
     
        public bool IsInvalid { get { return IsClosed; } }  
     
        public bool ReleaseHandle() {  
            terminator();  
            MclWrapper.LibUnloaded();  
            return true;  
        }  
    }  
     
    public static class MclWrapper {  
        // safe handle to make sure the library will be unloaded correctly  
        private static MatLibHandle handle =  
            new MatLibHandle(mclInitializeApplication, mclTerminateApplication);  
     
        // methods that simulate "GC.KeepAlive(handle)"  
        public static void Init() { /* do nothing; make sure the class is loaded */ }  
        public static void LibUnloaded() { /* do nothing; make sure the class is not unloaded */ }  
     
        // release library  
        public static void Dispose() { handle.Dispose(); }  
     
        // external methods  
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
        [DllImport("mclmcr.dll")]  
        private static extern bool mclInitializeApplication();  
     
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
        [DllImport("mclmcr.dll")]  
        private static extern void mclTerminateApplication();  
    }  
     
    // Then for each library to be loaded:  
    public static class MyLibWrapper {  
        private static MatLibHandle handle =  
            new MatLibHandle(MyLibInitialize, MyLibTerminate());  
     
        public static void Dispose() { handle.Dispose(); }  
     
        public static void DoSomething() { MyLibDoSomething(); }  
     
        // external methods  
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
        [DllImport("mylib.dll")]  
        private static extern bool MyLibInitialize();  
     
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]  
        [DllImport("mylib.dll")]  
        private static extern void MyLibTerminate();  
     
        [DllImport("mylib.dll")]  
        private static extern void MyLibDoSomething();  
    Friday, December 5, 2008 1:52 PM