不会释放的静态变量

本文关键字:静态 变量 释放 | 更新日期: 2023-09-27 18:00:52

我的类中有一个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();
    }

不会释放的静态变量

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

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

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

关闭应用程序后,对象是否得到妥善处理?

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

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

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

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

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

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

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

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事件中处理静态变量

当你说"多次启动和停止这个应用程序"时,你的意思是进程退出,每次都启动一个新进程吗?当进程退出时,操作系统会回收其所有内存,因此在实践中不会出现"内存泄漏"。

话虽如此,我确实觉得在关闭时清理资源是一种很好的做法;您可能决定要在同一进程中重新启动。修复泄漏比一开始就不修复要困难得多。

假设您必须执行其他操作,比如在关闭时刷新写入程序。然后,您将需要某种钩子,它在关闭时启动。

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

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

}