【问题标题】:Should one call Dispose for Process.GetCurrentProcess()?是否应该为 Process.GetCurrentProcess() 调用 Dispose?
【发布时间】:2015-01-19 11:22:06
【问题描述】:

例如,见

How to get the current ProcessID?

没有人愿意为System.Diagnostics.Process.GetCurrentProcess() 返回的对象调用 Dispose。它真的应该被调用吗?请解释原因。

【问题讨论】:

  • 简单:如果它实现了IDisposable,则调用Dispose。它可能会或可能不会保留对非托管内存或其他资源的句柄,您只是不知道当前的实现,所以这样做。
  • 您不必调用它。所以你得到了是和否的答案,你仍然什么都不知道。不要问这个问题。您可以随时处置,您永远不会出错。或者你花一分钟编写一个小测试应用程序,它会执行一亿次。现在你知道真正的答案了。

标签: c# .net idisposable


【解决方案1】:

是的,实际上它也很重要。如果您看到实际的source,您会看到Dispose 不仅继承自Component,它也有一些作用。

在我看来,查看该代码,将EnableRaisingEvents 设置为true 是最重要的,因为这涉及创建等待句柄。需要释放该句柄以防止内存和句柄泄漏。

【讨论】:

  • 没有泄漏。等待句柄的延迟释放是非常无辜的,它们是您可以分配的最便宜的操作系统对象。他也不太可能为自己的进程订阅 Exited 事件;)
  • @HansPassant:我猜这个链接只是一个示例。当您使用句柄进行繁重的处理时,您可能会用完它们。这一切都无关紧要,如果对象实现了IDisposable,你应该调用Dispose
  • 这就是货物崇拜的方法。它并不真正属于像 SO 这样的网站。但很难摆脱。
  • 数据看。 Een infoatief antwoord neemt niet aan dat wat iedereen doet is automaties het korrekte antwoord。 Hebt je het geprobeert? Makkelijk te doen。
  • @HansPassant:哈哈。英语更好。你的荷兰语有点生疏了。
【解决方案2】:

这是一个艰难的决定。

如果您没有触摸Handle 属性以及其他一些敏感点,您可能不必为从Process.GetCurrentProcess() 获得的Process 实例调用Dispose

让我们看一下包含Dispose逻辑精髓的Process.Close方法。

    public void Close()
    {
        if (this.Associated)
        {
            if (this.haveProcessHandle)
            {
                this.StopWatchingForExit();
                this.m_processHandle.Close();
                this.m_processHandle = null;
                this.haveProcessHandle = false;
            }
            this.haveProcessId = false;
            this.isRemoteMachine = false;
            this.machineName = ".";
            this.raisedOnExited = false;
            this.standardOutput = null;
            this.standardInput = null;
            this.standardError = null;
            this.Refresh();
        }
    }

只有当Process 实例有一个进程句柄时,你才能看到真正发生的事情。 Refresh 方法对我们的主题没有任何兴趣。

如果您进一步观察,您会发现当访问Handle 属性时,Process 实例可以获取(并因此持有)进程句柄。这不是唯一的情况

    public IntPtr Handle
    {
        get
        {
            this.EnsureState(Process.State.Associated);
            return this.OpenProcessHandle().DangerousGetHandle();
        }
    }

作为一般规则:如果它实现了IDisposable - 你应该调用Dispose

在您的特定情况下,如果您只触摸当前进程名称或其他内容,则可以省略 Dispose 调用并侥幸逃脱。

这是一个例子:

        Process process = Process.GetCurrentProcess();

        var fieldInfo = typeof(Process).GetField("haveProcessHandle", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        var v1 = fieldInfo.GetValue(process);
        //v1 is false. Explicit Dispose is not necessary.

        var processName = process.ProcessName;
        var v2 = fieldInfo.GetValue(process);
        //v2 is false. Explicit Dispose is not necessary.

        var processHandle = process.Handle;
        var v3 = fieldInfo.GetValue(process);
        //v3 is true. Bah. Explicit Dispose IS necessary from now on.

我使用反射的唯一原因是:如果您通过 Visual Studio 调试器监视 process 变量,它将遍历属性并读取可怕的 Handle 属性。

Process 类是“不良设计模式”的完美示例,因为它极大地改变了 get 访问器中的对象状态。

【讨论】:

    猜你喜欢
    • 2011-06-30
    • 2015-09-07
    • 2014-04-06
    • 2010-11-17
    • 2023-01-10
    • 2011-11-23
    • 2012-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多