Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GC.KeepAlive versus using

In his article about preventing multiple instances of an application, Michael Covington presents this code:

static void Main()                  // args are OK here, of course
{
    bool ok;
    m = new System.Threading.Mutex(true, "YourNameHere", out ok);

    if (! ok)
    {
        MessageBox.Show("Another instance is already running.");
        return;
    }

    Application.Run(new Form1());   // or whatever was there

    GC.KeepAlive(m);                // important!
}

He explains that the GC.KeepAlive(m) is required to prevent the garbage collector from collecting the mutex early, since there are no additional references to it.

My question: will wrapping the mutex in a using do the same thing? That is, will the following also prevent the GC from pulling the rug out from under me?

static void Main()                  // args are OK here, of course
{
    bool ok;
    using (var m = new System.Threading.Mutex(true, "YourNameHere", out ok))
    {
        if (! ok)
        {
            MessageBox.Show("Another instance is already running.");
            return;
        }

        Application.Run(new Form1());   // or whatever was there
    }
}

My gut reaction is that the using will work, since using is (supposed to be) equivalent to:

Mutex m = new System.Threading.Mutex(true, "YourNameHere", out ok);
try
{
    // do stuff here
}
finally
{
    m.Close();
}

And I would think that the m.Close() there would be enough to signal to the JIT compiler that there's another reference, thus preventing premature garbage collection.

like image 640
Jim Mischel Avatar asked Mar 11 '09 17:03

Jim Mischel


People also ask

What does GC KeepAlive do?

The purpose of the KeepAlive method is to ensure the existence of a reference to an object that is at risk of being prematurely reclaimed by the garbage collector.

What is the purpose of GC ReRegisterForFinalize () method?

The ReRegisterForFinalize method adds the obj parameter to the list of objects that request finalization before the garbage collector frees the object. The obj parameter must be the caller of this method.

What is SuppressFinalize?

SuppressFinalize() system method is designed to prevent calling the finalizer on the specified object. If an object does not have a destructor, invoking SuppressFinalize on this object has no effect and ReSharper flags such call as redundant. To learn more how the destructor works, see Object.

Why we use GC collect?

Use this method to try to reclaim all memory that is inaccessible. It performs a blocking garbage collection of all generations. All objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected.


2 Answers

Wrapping the mutex in a using statement will indeed prevent it from being garbage collected, but will also dispose of it (it calls Dispose, not Close) at the end (whereas GC.KeepAlive won't, obviously).

If the end of the method is genuinely going to be the end of the process, I don't believe it's likely to make any practical difference which you use - I prefer the using statement on the general principle of disposing of anything which implements IDisposable.

If the mutex hasn't been disposed when the process exits, I suspect its finalizer will take care of it - so long as other finalizers don't hog the finalization thread beyond its timeout.

If the finalizer doesn't take care of it, I don't know whether Windows itself will notice that the process can't possibly own the mutex any more, given that it (the process) doesn't exist any more. I suspect it will, but you'd have to check detailed Win32 documentation to know for sure.

like image 179
Jon Skeet Avatar answered Nov 03 '22 02:11

Jon Skeet


Using using seems to be a better fit in this case than using GC.KeepAlive. You not only want to keep the Mutex alive as long as the application is running, you also want it to go away as soon as you exit the main loop.

If you just leave the Mutex hanging without disposing it, there may be some time before it's finalized, depending on how much cleanup work there is to do when the application is shutting down.

like image 5
Guffa Avatar answered Nov 03 '22 03:11

Guffa