1

我的班级中有一个static StreamWriter变量:

private static StreamWriter streamWriter = CreateStreamWriter(pathToFile);

我没有在我的应用程序中关闭此 StreamWriter,因为它需要在应用程序运行时打开。

如果我多次启动和停止此应用程序,我会出现内存泄漏吗?还是在关闭应用程序时正确处理了对象?

此类是 ASP.NET MVC 4 和 WPF 应用程序都使用的实用程序类。

感谢大家的回复。这是我添加的代码:

在包含 StreamWriter 的类中:

public static void OnApplicationExit(object sender, EventArgs e)
{
    try
    {
        streamWriter.Flush();
        streamWriter.Close();
        streamWriter.Dispose();
    }
    catch { }
}

public static void OnApplicationExit()
{
    try
    {
        streamWriter.Flush();
        streamWriter.Close();
        streamWriter.Dispose();
    }
    catch { }
}

在 ASP.NET MVC Global.Asax 中:

    protected void Application_End()
    {
        Utilities.MyClass.OnApplicationExit();
    }
4

5 回答 5

5

如果我多次启动和停止此应用程序,我会出现内存泄漏吗?

不会。当进程结束时,与进程关联的所有资源都会自动返回给操作系统。这是 Windows 的一个功能;所有进程都是如此,而不仅仅是托管代码进程。

正如其他人指出的那样,您可能会丢失数据,但不会泄漏内核对象

关闭应用程序后对象是否正确处理?

不必要。如果应用程序因“快速失败”而终止,那么显然没有终结器运行,因为没有任何东西运行。如果应用程序被未处理的异常终止,那么终结器是否运行是实现定义的。

此外,正如 Raymond Chen 曾经指出的那样,当您知道进程正在关闭时运行终结器就像在拆除建筑物之前扫地一样。这是浪费时间和精力。

简而言之,您不应该依赖运行终结器来确保程序的正确性。

于 2013-02-24T15:22:12.807 回答
4

StreamWriter不保证在应用程序关闭时被释放。有时会,但在某些情况下这是不可能的。

没有内存泄漏,因为它使用托管内存。当应用程序关闭时,整个堆被删除。

这也不是资源泄漏,因为打开的文件句柄将在应用程序关闭时关闭。

但是,StreamWriter如果没有处理,则有一个不会刷新的缓冲区。这意味着您使用 writer 编写的最后内容可能会从文件中丢失。

于 2013-02-24T04:20:01.520 回答
2

Streamwriter 实现 IDisposable。所以如果你不调用它的 Dispose 方法,你就不能保证你正确地处理了它的资源。

在我看来,您有两个基本选择:

  1. 保留 StreamWriter 的静态实例,但在应用程序关闭时捕获,然后调用 Streamwriter.Dispose() 以释放资源。我不知道您的应用程序是 WPF 还是 Windows 窗体应用程序,但如果您可以找到在应用程序关闭时触发的事件,您可以在那里调用 dispose。我认为Application.ApplicationExit可能是您需要的。

  2. 将 StreamWriter 转换为实例变量,使用 using 语句对其进行实例化,执行 IO,然后立即处理它:

    using(var writer = new StreamWriter())
    {
        //do your IO here
    }
    

编辑:您指出您的应用程序是 ASP.Net 应用程序。对于 ASP.Net 应用程序,您可以在 global.asax 的 Application_Start 事件中创建静态变量,并在 global.asax 的 Application_End 事件中处置静态变量。

于 2013-02-24T04:22:38.803 回答
1

当您说“多次启动和停止此应用程序”时,您的意思是该进程退出并且您每次都启动一个新进程吗?当一个进程退出时,它的所有内存都会被操作系统回收,所以实际上没有“内存泄漏”。

话虽如此,我确实觉得在关机时清理资源是个好习惯;您可能决定确实要在同一进程中重新启动。修复泄漏比一开始就没有泄漏要困难得多。

假设您必须在关闭时执行其他操作,例如刷新写入器。然后,您需要某种在关机时启动的钩子。

于 2013-02-24T04:22:02.737 回答
-1

使用 using 语句,这是最好的方法。

使用 (var r = new StreamWriter(,,)) {

}

于 2013-02-24T04:14:13.297 回答