Logo 
Search:

.Net Framework FAQ

Submit Interview FAQ
Home » Interview FAQ » .Net FrameworkRSS Feeds

When do I need to use GC.KeepAlive?

  Shared By: Bellona Lopez    Date: Sep 06    Category: .Net Framework    Views: 1552

Answer:

It's very unintuitive, but the runtime can decide that an object is garbage much sooner than you expect. More specifically, an object can become garbage while a method is executing on the object, which is contrary to most developers' expectations. Chris Brumme explains the issue on his blog. I've taken Chris's code and expanded it into a full app that you can play with if you want to prove to yourself that this is a real problem:

using System;
using System.Runtime.InteropServices;

class Win32
{
[DllImport("kernel32.dll")]
public static extern IntPtr CreateEvent( IntPtr lpEventAttributes,
bool bManualReset,bool bInitialState, string lpName);

[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool CloseHandle(IntPtr hObject);

[DllImport("kernel32.dll")]
public static extern bool SetEvent(IntPtr hEvent);
}

class EventUser
{
public EventUser()
{
hEvent = Win32.CreateEvent( IntPtr.Zero, false, false, null );
}

~EventUser()
{
Win32.CloseHandle( hEvent );
Console.WriteLine("EventUser finalized");
}

public void UseEvent()
{
UseEventInStatic( this.hEvent );
}

static void UseEventInStatic( IntPtr hEvent )
{
//GC.Collect();
bool bSuccess = Win32.SetEvent( hEvent );
Console.WriteLine( "SetEvent " + (bSuccess ? "succeeded" : "FAILED!") );
}

IntPtr hEvent;
}

class App
{
static void Main(string[] args)
{
EventUser eventUser = new EventUser();
eventUser.UseEvent();
}
}
If you run this code, it'll probably work fine, and you'll get the following output:

SetEvent succeeded
EventDemo finalized
However, if you uncomment the GC.Collect() call in the UseEventInStatic() method, you'll get this output:

EventDemo finalized
SetEvent FAILED!
(Note that you need to use a release build to reproduce this problem.)

So what's happening here? Well, at the point where UseEvent() calls UseEventInStatic(), a copy is taken of the hEvent field, and there are no further references to the EventUser object anywhere in the code. So as far as the runtime is concerned, the EventUser object is garbage and can be collected. Normally of course the collection won't happen immediately, so you'll get away with it, but sooner or later a collection will occur at the wrong time, and your app will fail.

A solution to this problem is to add a call to GC.KeepAlive(this) to the end of the UseEvent method, as Chris explains.

Share: 
 

Didn't find what you were looking for? Find more on When do I need to use GC.KeepAlive? Or get search suggestion and latest updates.


Your Comment
  • Comment should be atleast 30 Characters.
  • Please put code inside [Code] your code [/Code].


Tagged: