不会丢弃的静态变量

时间:2013-02-24 04:13:16

标签: c# memory-management memory-leaks dispose resource-management

我班上有一个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();
    }

5 个答案:

答案 0 :(得分:5)

  

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

没有。当进程结束时,与进程关联的所有资源都将自动返回到操作系统。这是Windows的一个功能;它适用于所有流程,而不仅仅是托管代码流程。

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

  

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

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

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

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

答案 1 :(得分:4)

当应用程序关闭时,不保证StreamWriter被处理掉。有时它会,但在某些情况下是不可能的。

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

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

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

答案 2 :(得分: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
    }
    
  3. 修改:您表示您的应用是ASP.Net应用。对于ASP.Net应用程序,可以在global.asax的Application_Start事件中创建静态变量,并在global.asax的Application_End事件中处理静态变量。

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:-1)

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

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

}