views:

60

answers:

4

Is the Close() method required for the System.Diagnostics.Process class?

EDIT: The Process is monitoring a console application which terminates almost instantly...

Billy3

A: 

It's not fatal - the garbage collector will call Process's finalizer eventually, and the object's resources will be cleaned up that way.

It's good practice, though, to free up the resources as soon as they're not needed, by calling Close directly, or wrapping the code in a using block. This way you reduce the load on the garbage collector, and you free up a little bit of memory earlier rather than later.

Tim Robinson
+1  A: 

No, not necessarily.

It is typically a good practice to always call Dispose() (or wrap in a using statement) any IDisposable, such as a Process instance. However, if this is properly written, the GC will eventually perform all of the cleanup in the finalizer, even if you do not.

Depending on the resources allocated, this may be a significant "hit" on memory/resources for a period of time, or not. In the case of a Process, you're going to be holding onto a process handle (which is relatively small) until the GC collects and finalizes the object, which probably will not have much of an impact on your program overall.

Reed Copsey
I don't think that Close will ever attempt to shut down the process. Just dug through the Close code in reflector a few minutes ago because I wasn't sure exactly what this API did.
JaredPar
http://stackoverflow.com/questions/673031/process-close-is-not-terminating-created-process-c
Adam Robinson
Process.Close() does *not* try to kill or shutdown the process.
Hans Passant
Furthermore, I would be hesitant to believe that Microsoft would publish a component that implements `IDisposable` that has a particularly common usage path that requires that you rely on the GC to invoke the finalizer. If `Close` terminated the process and the object were collected very quickly, you'd still be terminating the process early.
Adam Robinson
@JadedPar / @Hans: Sorry - was thinking of the wrong method - edited my answer to be more correct now.
Reed Copsey
@Reed: +1 for correcting your answer.
Billy ONeal
A: 

Close (or Dispose) will release (granted probably a relatively small amount of) operating system wide resources. These are things that you share with every other process on the system, so to be a good citizen you should release them in a timely as possible fashion.

Ultimately though they will be released by way of the garbage collector running finalizers or when your process terminates.

Logan Capaldo
What operating system wide item could that be? The win32 process model on top of which the Process class is built has only process handles, which are per thread, not operating system wide.
Billy ONeal
.NET is not exclusively Win32. C# code running on Mono/Linux might need to worry about things like Unix file handles, which are a system-wide resource.
Karmastan
@Billy Process handles refer to a kernel object ultimately. Things like the exit code for the process, etc. need to be stored somewhere and kept around until all the handles to that process are gone.
Logan Capaldo
@Logan: Kernel objects are typically per thread, not global.
Billy ONeal
@Billy there is at least one kernel object for the process, that stores things like the exit code. There is only one of those, because there is only one process. It sticks around until all the HANDLEs to that process are gone. More than one thread can interrogate a process for things like its exit code (through APIs like OpenProcess etc.), so that object has to stick around until all the handles to the process are gone, even if the process itself has terminated.
Logan Capaldo
@Logan: The global state of a process is destroyed when that process exits. There has to be a small amount of memory (Less than 100 bytes) retained for little things like that, but that's by no means going to significantly affect global state.
Billy ONeal
I specifically said "granted probably a relatively small amount of". It's not like I said "if you don't close the handle you'll leak a gig of global memory". If you know what the operating system wide item is (that 100 bytes or so) I don't know why you asked the original question.
Logan Capaldo
+1  A: 

Yes.

Note, however, that Close simply has to do with releasing resources that are local to your application. It does not attempt to terminate the process. To do that, you'd have to call either CloseMainWindow() (for GUI applications) or Kill() (for any application).

The Process class implements IDisposable, which, strictly speaking, obligates you to calling Dispose once you're finished with the object. However, for many classes like this, the public-facing version of the Dispose method is Close.

The easiest (and most reliable) way of dealing with such objects is with a using block. This will automatically call Dispose on the variable as soon as the end of the block is reached. It also protects you from an exception preventing you from disposing of the object.

For example:

using(System.Diagnostics.Process process = new System.Diagnostics.Process())
{
    // set your properties and launch it
    // wait for it to exit if you want to, or just let it continue to run
}

This is functionally equivalent to doing this:

System.Diagnostics.Process process = new System.Diagnostics.Process();

try
{
    // set your properties and launch it
    // wait for it to exit if you want to, or just let it continue to run
}
finally
{
    process.Close();
}

(Note that I said functionally equivalent, not semantically equivalent; in reality, the using block maintains its own handle to the object as an IDisposable, then calls Dispose, not Close. That, however, is not relevant to this question.)

Adam Robinson
If I was dealing with the raw process, that's exactly what I'd do. Unfortunately it's wrapped a few levels of indirection away from the object which would control the lifetime of the process.
Billy ONeal
Typically, it's good practice to always dispose any IDisposable, but a properly written one will get handled by the finalizer if you don't - and there are cases where this makes more sense.
Reed Copsey
@Reed: `System.Diagnostics.Process.Close()` does not send a WM_CLOSE message to the process. You're thinking of `System.Diagnostics.Process.CloseMainWindow()`.
Billy ONeal
@Reed: I'm sorry, but you're simply incorrect. I just made a sample application that launches `Notepad` with the process inside a `using` block. Notepad remains open after the block completes. `Close` is not a directive to terminate the process.
Adam Robinson
@Reed: In addition, the usage of finalizers to dispose of limited resources is purely a defensive programming technique, *not* a designated code path. I would challenge you to come up with a scenario where, barring poor design of existing components, `Dispose` cannot be called deterministically to achieve whatever functionality is required.
Adam Robinson
@Billy: Given that you're dealing with it abstracted, your only choices are either to refactor the existing code to expose an API to dispose of the process deterministically (obviously not a desirable solution), or you can rely on the fallback of the GC to call the finalizer. This is definitely *not* a good path to follow, but the finalizer will be called at some point; it may just not be until the your application terminates. In any event, unless you're launching a ton of processes, leaking process handles is not the absolute end of the world.
Adam Robinson