【问题标题】:How to dispose a System.Diagnostics.Process object without killing process?如何在不杀死进程的情况下处理 System.Diagnostics.Process 对象?
【发布时间】:2015-05-28 14:53:44
【问题描述】:

我有一个创建 Process 对象以启动外部应用程序的应用程序。一旦它验证应用程序已正确启动,它就不再关心它,所以我不再需要 Process 对象,但我不能调用 Dispose() 因为我不想关闭进程。解决方法是什么?

【问题讨论】:

  • 为什么需要处理掉它?
  • @DStanley 因为它实现了 IDisposable。您总是需要处理这些对象,否则您将泄漏句柄或其他非托管资源。
  • @amnesia 你确定它会终止进程吗?你试过了吗?
  • @antiduh 可悲的是,重复的回复只说“你真的应该处理它”,但没有说它是否会杀死进程:-)
  • 投票重新开放。正如@xanatos 指出的那样,欺骗目标及其答案并未解决处置 Process 对象是否会杀死进程的问题。

标签: c# .net


【解决方案1】:

您可以放心地 Dispose 流程实例,该流程将在之后运行。

class Program
{
    static void Main(string[] args)
    {
        Process p = new Process
        {
            StartInfo = {FileName = "notepad.exe"}
        };
        p.Start();

        p.Dispose();
        // Notepad still runs...
        GC.Collect(); // Just for the diagnostics....
        // Notepad still runs...
        Console.ReadKey();
    }
}

实际上,该进程 (Notepad.exe) 甚至会在您的 .NET 应用程序终止后运行。顺便说一句,这是我建议不要担心进程实例并在进程实际终止之前处理它们的原因之一:您将失去控制句柄来停止操作系统进程或查询它们的状态。除非你有无数的 Process 实例,否则我不应该担心它们。

【讨论】:

  • 哇,我是个白痴,我只是假设没有测试。谢谢你的证明。
  • 告诉某人不要费心处理某物是一个糟糕的建议——它是一次性的,这是有原因的。原因是Process 对象在其有效时持有机器范围 资源(进程句柄)。 Process 实现了一个终结器,因此一旦构造完成就立即注册到终结器队列中;除非您致电 Dispose(),否则它将保留在该队列中。需要运行 GC 来发现对象已被释放,运行终结器来运行终结器并释放这些句柄,然后再运行 GC 来回收对象的内存。 始终丢弃一次性用品
  • 要详细了解为什么应该处置 Process 对象,请参阅此答案:stackoverflow.com/questions/16957320/…
  • antiduh:你完全正确,我的意思是“建议不要担心进程实例并在进程实际终止之前处理它们”。我已经编辑了我的答案
【解决方案2】:

我认为Process.Close()Process.Dispose() 不要杀死进程。他们只是释放一些与处理流程相关的资源。

来自reference source

protected override void Dispose(bool disposing) {
    if( !disposed) {
        if (disposing) {
            //Dispose managed and unmanaged resources
            Close();
        }
        this.disposed = true;
        base.Dispose(disposing);                
    }            
}

public void Close() {
    if (Associated) {
        if (haveProcessHandle) {
            StopWatchingForExit();
            Debug.WriteLineIf(processTracing.TraceVerbose, "Process - CloseHandle(process) in Close()");
            m_processHandle.Close();
            m_processHandle = null;
            haveProcessHandle = false;
        }
        haveProcessId = false;
        isRemoteMachine = false;
        machineName = ".";
        raisedOnExited = false;

        //Don't call close on the Readers and writers
        //since they might be referenced by somebody else while the 
        //process is still alive but this method called.
        standardOutput = null;
        standardInput = null;
        standardError = null;

        output = null;
        error = null;

        Refresh();
    }
}

我没有看到任何应该终止进程的东西。

【讨论】:

  • 你的最终结论是对的,但是来源并不能证明这一点:我们看不到 base.Dispose(disposing); 中发生了什么。
  • @g.pickardou 但我有:-) 基类是Component,它的Dispose 做了一些Component 清理工作。而最后,this.m_processHandle.Close();之后Process(类)就不能再控制进程了,因为那是它的WindowsHANDLE对进程的控制。
  • 我相信你看到了,我刚才提到提供的样本并不能证明这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-08
  • 1970-01-01
  • 2012-02-19
相关资源
最近更新 更多