Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# garbage collector seems to be closing my StreamWriter too early

I have a logger class thats a singleton. In it's destructor I call Close() which prints the footer for the log and then closes the StreamWriter.

 public void Close()
    {
        WriteLogFileFooter();

        _logFile.Flush();

        _logFile.Close();
    }

The problem is when System.Enviornment.Exit(1) is called from elsewhere in the program (portions that I didn't write myself), the footer is never printed and my logger throws an exception for trying to write to a closed stream. I can only assume the Exit command is causing my StreamWriter to be closed before my Singleton is destructed. I tried to use GC.SupressFinalize() on my StreamWriter but that didn't seem to help.

like image 260
ForeverNoobie Avatar asked Jul 05 '12 16:07

ForeverNoobie


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.


2 Answers

You are violating one explicit rule for finalizers:

The Finalize method should not reference any other objects.

http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=VS.90).aspx

It's entirely possible that the managed object you hold a reference to is collected before your object is collected when the application exits.

UPDATE

If you need to clean up managed resources when the application exits, you could hook up the ProcessExit event of AppDomain rather than rely on non-deterministic behavior of finalizer execution.

.NET Console Application Exit Event

like image 164
Eric J. Avatar answered Oct 06 '22 22:10

Eric J.


You should make your logger implement IDisposable, and use it in a using block. This means that it will be deterministically disposed, whereas now it is being nondeterministically destructed.

The cause of the error is that your stream will sometimes be closed before the logger, as Exit basically destroys everything (nondeterministically) and quits. You should use a deterministic pattern (IDisposable) to avoid this.

In reality, destructors are rarely useful in C#, for the precise reason that they are non-deterministic. They only are worth using for releasing unmanaged resources.

Also, implementing IDisposable may make it inconvenient to use a singleton. I personally think it's better to create an instance to be used throughout the program and disposed at the end, rather than an explicit singleton.

like image 32
Kendall Frey Avatar answered Oct 07 '22 00:10

Kendall Frey