Process.Dispose()实际上是做什么的?

49
在C#中,class Process继承自class Component,后者实现了IDisposable接口,因此我可以在任何Process对象上调用Dispose()方法。我真的必须这样做吗?我如何知道是否真的需要这样做?
假设我有以下代码:
 var allProcesses = System.Diagnostics.Process.GetProcesses();
 var processesNames = processes.Select( p => p.ProcessName );
 // output process names here

现在看起来我有一个Process对象数组,我需要编写一个try-finally来遍历整个数组并且对每个对象调用Dispose()方法。这显然会增加很多冗余代码。

Dispose()方法对Process对象有什么作用?我是否确实需要为每个Process对象都调用Dispose()方法?如果需要,我该如何判断?

2个回答

45
我真的需要为每个进程对象调用 Dispose() 并且如何决定是否需要这样做? 是的,您应该将它们处理掉。请注意在Process文档中的此文本: 系统进程由其进程标识符在系统上唯一标识。像许多Windows资源一样,进程也通过其可能不在计算机上唯一的句柄来标识。 句柄是资源的标识符的通用术语。即使进程已退出,操作系统仍会保留进程句柄,通过Process组件的Handle属性访问句柄。 因此,您可以获取进程的管理信息,例如ExitCode(通常为零表示成功或非零错误代码)和ExitTime。 句柄是一种极其有价值的资源,因此泄漏句柄比泄漏内存更具有毒性。 因此,如果您不Dispose它们,则可能会泄漏句柄(直到垃圾收集它们 - 但Dispose 的整个目的是允许早期清理资源)
同时,请注意,相同的文档指出Process覆盖Dispose(bool) - 这表明在调用Dispose时它实际上正在执行某些操作

4
我很喜欢在这里使用 using (IEnumerable<IDisposable> ...) :) - eFloh
2
@eFloh - 不确定你的目标是什么。using语句引入了一个新变量和一个作用域,在该作用域中将使用该变量。因此,虽然using只能用于可处理对象,但几乎总是要利用它们在该作用域内的“非一次性”方面。 - Damien_The_Unbeliever
1
很好的建议。然而,看一下Process.GetProcessByName()的实现,微软甚至不会在枚举机器上的每个进程之后这样做。进程枚举将打开大量进程句柄,因此您需要等待GC周期,然后才能重新使用ID。 - Mark
3
我更倾向于使用“Dispose”而不是“Close”,在这种情况下它们的关系是相反的(“Dispose”调用“Close”)。但是,“Dispose”还会执行少量额外的清理工作(例如取消注册该实例以进行最终处理),这将使事情更加“清洁”。 - Damien_The_Unbeliever
2
@Harry - 当然,还有CloseHandle:“关闭进程句柄不会终止关联的进程或删除进程对象。要删除线程对象……” - Damien_The_Unbeliever
显示剩余6条评论

-1

3
我没有点踩,但这并没有真正回答问题,它只是解释了“一般情况下”Dispose方法的作用(我假设OP已经知道)。 - EJoshuaS - Stand with Ukraine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接