48

In C# class Process inherits from class Component that implements IDisposable and so I can call Dispose() on any Process object. Do I really have to? How do I know if I really have to?

Suppose I have the following code:

 var allProcesses = System.Diagnostics.Process.GetProcesses();
 var processesNames = processes.Select( p => p.ProcessName );
 // output process names here

Now it looks like I have an array of Process objects and I have craft a try-finally to traverse the array and Dispose() each object. That's definitely lots of extra code.

What does that Dispose() do for Process objects? Do I really need to Dispose() every Process object and how do I decide if I need to do so?

sharptooth
  • 167,383
  • 100
  • 513
  • 979

2 Answers2

45

Do I really need to Dispose() every Process object and how do I decide if I need to do so?

Yes, you should dispose them. Note this text in the documentation for Process:

A system process is uniquely identified on the system by its process identifier. Like many Windows resources, a process is also identified by its handle, which might not be unique on the computer. A handle is the generic term for an identifier of a resource. The operating system persists the process handle, which is accessed through the Handle property of the Process component, even when the process has exited. Thus, you can get the process's administrative information, such as the ExitCode (usually either zero for success or a nonzero error code) and the ExitTime. Handles are an extremely valuable resource, so leaking handles is more virulent than leaking memory.

So if you don't Dispose them, you're potentially leaking the handles (until they're garbage collected - but the whole point of Dispose is to allow early cleanup of resources)


Note, also, that the same documentation indicates that Process overrides Dispose(bool) - another clue that it actually does something when Dispose is called.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • 4
    I would love a `using (IEnumerable ...)` here :) – eFloh Jan 26 '15 at 17:46
  • 2
    @eFloh - not sure what you're aiming for there. A `using` statement introduces a new variable and a scope in which that variable will be used. So whilst a `using` can only be used for disposable objects, the point is almost always to make use of their "non-disposable" aspects within that scope. – Damien_The_Unbeliever Jan 26 '15 at 17:51
  • 1
    just a nice syntaqx shortener... Specifically for these cases where you have a whole list of disposables, it would be nice to have a syntax to finally dispose them off without the need of a `finally {foreach(...x...){ x.Dispose(); }}` – eFloh Jan 26 '15 at 17:58
  • 1
    Great advice. However, looking at the implementation of Process.GetProcessByName(), MS doesn't even bother to do this after enumerating every process on the machine. Process enumeration will open a ton of process handles, so you'll need to wait for a GC cycle before the IDs can be re-used. – Mark Jul 22 '15 at 09:57
  • 1
    @Mark I don't know what framework version you checked, but in 4.6.2 `Process.GetProcessesByName()` does dispose the processes that are not returned. See [Reference Source](http://referencesource.microsoft.com/#System/services/monitoring/system/diagnosticts/Process.cs,c955a482994fbefb). – cremor Sep 20 '16 at 07:08
  • @cremor You're right - looks like they fixed it in 4.5. – Mark Sep 21 '16 at 20:39
  • To be clear, Close() will call Dispose(), right? Is it generally preferable then to call Close()? – Kyle Delaney Mar 27 '18 at 19:14
  • 3
    @KyleDelaney - no, I'd prefer `Dispose` over `Close`. The relationship is the other way around in this case (`Dispose` calls `Close`). But `Dispose` will also perform a small amount of additional cleanup (such as unregistering this instance for finalization) which will leave things "cleaner". – Damien_The_Unbeliever Mar 28 '18 at 05:22
  • 1
    I don't understand how can I be leaking handles, if I didn't create the process? When I created the process, I am responsible for freeing the handle (via Dispose()). If the process is external to my code, I can't free its handle without terminating the process first. I read many .NET Win32 related objects work like that - they CAN create handles, but not always. If you don't create a handle - then theoretically - dispose should do nothing. – Harry Sep 17 '19 at 19:14
  • 1
    @Harry - there's a link to the reference source a few comments up. You're welcome to look through it, and of course check the documentation. There are public methods for obtaining a handle or for enabling events, both of which call `GetProcessHandle` that, if it doesn't already have one, ends up calling either `OpenProcess` or `DuplicateHandle`. Both of these create new handles. – Damien_The_Unbeliever Sep 18 '19 at 07:04
  • 2
    @Harry - and, of course, [`CloseHandle`](https://learn.microsoft.com/en-gb/windows/win32/api/handleapi/nf-handleapi-closehandle): "Closing a process handle *does not terminate the associated process* or remove the process object. To remove a thread object..." – Damien_The_Unbeliever Sep 18 '19 at 07:05
-1

from MSDN: http://msdn.microsoft.com/en-us/library/3cc9y48w(v=vs.80).aspx

Call Dispose when you are finished using the Component. The Dispose method leaves the Component in an unusable state. After calling Dispose, you must release all references to the Component so the garbage collector can reclaim the memory that the Component was occupying.

CodeCamper
  • 6,609
  • 6
  • 44
  • 94
fatihk
  • 7,789
  • 1
  • 26
  • 48