我需要处理 Process.Start(url) 吗?

19

简单问题:我希望使用默认浏览器打开一个URL,所以我只需要使用Process.Start(url)。然而,我注意到这返回了一个IDisposable对象。

现在我想知道是否必须要对它进行处理?或者,换句话说,我的应用程序是否对该进程负责?预期的功能只是“点火并忘却”,我不希望我的应用程序作为新进程的父代,并且也不需要与其交互。

我在SO上看到了一些类似但不相关的问题,似乎只需在URL上调用Process.Start即可,但我不想遇到由于我的程序保持对长时间死亡的浏览器进程的引用而导致难以调试的内存泄漏/资源耗尽问题。

4个回答

12
不需要。
void Main()
{
    Process result = Process.Start("http://www.google.com");

    if (result == null)
    {
        Console.WriteLine("It returned null");
    }
}

打印

它返回了null

来自于MSDN(.NET Framework 4)上的Process.Start Method (String):

如果要启动的可执行文件地址是一个URL,则不会启动进程并且会返回null。

(通常,使用using语句是处理IDisposable对象的正确方法,除了WCF客户端之外。)


即使浏览器进程已经启动,它仍然返回 null! - AgentFire
@AgentFire 无论您的浏览器是否需要加载,对于URL,您始终会收到null。这就是重点 - 在这种特定情况下,您不必处置(URL)。 - TrueWill

11

如果你需要处理一个对象的释放,为什么不在代码块中套用 using 语句来确保GC(垃圾回收器)能够做必要的工作呢?这样可以实现“点火即忘”式的操作,但不会让内存或资源处于糟糕的状态。

可能有点杀鸡焉用牛刀,但在CodeProject上有一篇非常好的关于IDisposable接口的文章:http://www.codeproject.com/KB/dotnet/idisposable.aspx


问题在于我不完全理解这种情况下的对象生命周期。如果我使用(Process.Start(url));,那么它会在那个点等待吗?还是会过早地处理进程?目前来看,这在行为上没有任何区别,所以我“猜测”没有保持开放的资源,但我不确定,也不知道如何衡量。 - Michael Stum
由于“using”子句隐式地指示编译器构建try/finally并实现dispose,以及它们返回IDisposable对象的事实,我认为你可以放心这样做。如果不释放它,可能会占用资源。您可以尝试构建一个循环,打开多个URL而不将其处理掉,并查看资源是否失控,然后通过将它们包装在using子句中进行另一个测试。警告是之后您将有一堆窗口要关闭。 :) - Fooberichu

7

启动进程是一个本地调用,返回一个本地进程句柄,并存储在返回的进程实例中。Process类中有使用该句柄的方法,因此您可以执行等待进程退出或空闲的操作。

处理完Process后释放该句柄。我同意Jon的建议,将其包装在using语句中。


3
@Fooberichu的回答很到位,但我认为值得指出的是,通常只有少数几个东西“需要”显式释放。
对象总是在某个时候有效地被释放:
- 每当GC进行收集时,它将(最终)处理不再引用的对象。因此,如果您不手动释放,该对象可能会在它超出范围的几秒钟内被释放。 - 当您的应用程序退出时,它所持有的所有资源都将被释放。(尽管C#/.net可能不会处理对象的释放,但操作系统将收回几乎所有您的进程占用的任何内容。如果资源的生命周期超出了您的应用程序,则通常由操作系统负责清理它)
因此,手动释放(或使用'using')的目的不是确保资源将被释放,而是尽早释放它们。
现在,您不太可能耗尽大多数类型的资源(例如内存、文件句柄或系统画笔)。但是,如果您在不需要时保留资源,您的程序可能会变得不那么高效,可能会使用比必要更多的内存,或者通过暂时阻止其他应用程序执行有用的操作而导致延迟等。因此,释放资源是关于良好礼仪、整洁和消除不必要的低效性。
有一些情况下,资源必须被释放(例如,如果您不关闭文件,则无法从程序的其他位置或其他程序中打开/重命名/移动/删除它;如果您继续分配图形卡上的纹理而不释放它们,则会耗尽VRAM并导致计算机显示失败),但通常情况下,您很少遇到这些情况,如果您遵循最佳实践(在不再需要对象时显式释放对象),则通常不需要知道这些情况正在发生,因为您已经正确地处理它们。

2
在许多情况下,IDisposable类没有终结器。如果它们在没有被显式地处理的情况下被GC处理,那么与它们关联的任何非托管资源将被泄漏。框架类在大多数情况下都能很好地保护我们,但最佳做法是始终处置IDisposable对象。这种情况和WCF客户端恰巧是两种奇怪的边缘情况。 - TrueWill
每当垃圾收集器进行一次收集时,它将(最终)处理不再被引用的对象。因此,如果您不手动处理,对象可能仍会在其作用域结束后的几秒钟内被处理。这并不是完全保证的。Finalizer不能保证调用Dispose。它最终会进行垃圾回收(或许技术上说“很可能”),但并不一定调用Dispose。 - mjwills

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