Some notes on C# programming

Michael A. Covington
Institute for Artificial Intelligence
The University of Georgia
Athens, Georgia


Last revised 2004 February 20
Contents:
How long does a local variable exist?
What does Application.Run() really do?

How long does a local variable exist?

You might think that a local variable exists from the time it is created until the end of the part of the program in which it is visible. For example:
    static void Main()
    {
        int m;
        m = 2;
        Console.WriteLine(m);  // The last actual mention of m
.
.
.
        // Does m still exist here?
    }
The truth is, m may or may not exist at the end of Main().

The reason is optimized garbage collection. The .NET framework JIT compiler is smart enough to realize that the program actually stops using m quite a while before m goes out of scope. So it may garbage-collect m long before the end of the method.

How would you ever know that a variable has been garbage-collected after you stopped using it, but before it went out of scope? By definition, if you're not using it, then you won't be able to tell -- will you?

That's what the compiler thinks. But in fact, there are obscure situations where another process or thread relies on something continuing to exist in your thread, even after you've stopped using it. For an example involving mutexes, click here.

Worse, the garbage collector may or may not dispose of the variable "prematurely," depending on when garbage collection happens to take place, and whether you are running a debugger (which would insist on keeping the variables alive so it can watch them). So "bugs" of this kind may be hard to reproduce.

In that situation, you should add GC.KeepAlive(variable) at the last place where the variable needs to exist, in order to block garbage collection prior to that point. Here's the modified code:

    static void Main()
    {
        int m;
        m = 2;
        Console.WriteLine(m);  // The last actual mention of m
.
.
.
        GC.KeepAlive(m);       // Ensure that m still exists here
    }
Now m can't be disposed of until after the last GC.KeepAlive that references it.

What does Application.Run() really do?

Every windowed .NET application contains a call to Application.Run. This usually takes the form:
Application.Run(new Form1);
That is: Create an object of type Form1 and pass it to Application.Run.

However, let's consider, first, the simpler form:

Application.Run();
That means: Start a message-handling loop on the current thread, so that its windows will start responding to mouse clicks and other events. There can be as many such windows as you like. They must all exist and be visible.

The message-handling loop will continue until something in one of the windows does an Application.Exit(). When that happens, Application.Run will terminate, and the code after it in the main program, if any, will execute.

Normally, but not always, we pass Application.Run a window as an argument. That can be done as in the first example above, or you can do something like this:

Form1 f = new Form1();
Application.Run(f);
Now Application.Run will do three things: That is exactly what you want if f is the "main window" of the application.

There is a third way to call Application.Run, with an application context as its argument. That adds very little value, since Application.Run(new ApplicationContext(f)) is equivalent to Application.Run(f). However, the application context has a ThreadExit event and a few other hooks for slightly more versatility.

Microsoft's documentation for Application.Run is here.



The content and opinions expressed on this Web page do not necessarily reflect the views of,
nor are they endorsed by, the University of Georgia or the University System of Georgia.