473,725 Members | 1,942 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

TextWriter fails on Close() call in destructor

I have a log class that makes a synchronized TextWriter like so, in
the constructor:

StreamWriter sw = new StreamWriter(fi lename);
tw = TextWriter.Sync hronized(sw);

In the destructor, ~MyLogClass(), I call:

tw.WriteLine("s ome stuff");
tw.Close();

The Close() call throws an exception saying I can't do this on a
closed file. But, I don't close it anywhere! Is the file
automatically closed by the destructor before I get a chance to use
it? Are resources' Dispose() auto-invoked or something? What's
strange is that the WriteLine doesn't throw an exception (although its
contents never make it to the file).

Zytan

Mar 22 '07 #1
54 5212
On Mar 22, 4:58 pm, "Zytan" <zytanlith...@y ahoo.comwrote:
I have a log class that makes a synchronized TextWriter like so, in
the constructor:

StreamWriter sw = new StreamWriter(fi lename);
tw = TextWriter.Sync hronized(sw);

In the destructor, ~MyLogClass(), I call:

tw.WriteLine("s ome stuff");
tw.Close();
That's not a good idea to start with. Finalizers should only deal with
unmanaged resources. Bear in mind that by the time *your* finalizer
runs, the StreamWriter's finalizer may already have run. It sounds
like you may well not want a finalizer at all (they should be very
rare - basically only when you have direct access to unmanaged
resources, eg handles).

Instead, you should implement IDisposable and tell the caller to call
Dispose.
The Close() call throws an exception saying I can't do this on a
closed file. But, I don't close it anywhere! Is the file
automatically closed by the destructor before I get a chance to use
it? Are resources' Dispose() auto-invoked or something? What's
strange is that the WriteLine doesn't throw an exception (although its
contents never make it to the file).
The underlying stream has probably had its finalizer run already.
(Note that this is separate from a Dispose method. Often, and using
MS's pattern, a finalizer will call Dispose, but that's just a matter
of implementation, not something the CLR does for you.)

Jon

Mar 22 '07 #2
Jon, writers do not have a Finalize method. The underlying streams
have Finalize methods to close themselves. The result is that the
writer's buffer is never flushed to the stream before the stream is
closed, resulting in lost data (it's designed this way). I assume
WriteLine executes error free because no attempt is made to flush to
the closed stream.

Zytan, avoid Finalizers for unmanaged code because stuff like this
happens. Try a syntax like:
using (StreamWriter stream = new FileInfo(@"c:\t est123").Create Text())
{
stream.WriteLin e("blah blah blah");
}
Mar 22 '07 #3
james <ja********@gma il.comwrote:
Jon, writers do not have a Finalize method.
True, but streams do. I should have been more precise in my post.
Calling Close on the writer will call Close on the stream, which may
well have been finalized, hence the error.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Mar 22 '07 #4
No. The error occurs because calling close in the TextWriter flushes
it's buffer to the stream, which may have been finalized. You can
close the stream multiple times with no exception. For instance

tw.Close();
tw.Close();
tw.Close();

is perfectly legit.

Mar 22 '07 #5
james <ja********@gma il.comwrote:
No. The error occurs because calling close in the TextWriter flushes
it's buffer to the stream, which may have been finalized. You can
close the stream multiple times with no exception. For instance

tw.Close();
tw.Close();
tw.Close();

is perfectly legit.
Ah, I see. Thanks for correcting me. I really should read more
carefully :)

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Mar 22 '07 #6
I have a log class that makes a synchronized TextWriter like so, in
the constructor:
StreamWriter sw = new StreamWriter(fi lename);
tw = TextWriter.Sync hronized(sw);
In the destructor, ~MyLogClass(), I call:
tw.WriteLine("s ome stuff");
tw.Close();

That's not a good idea to start with. Finalizers should only deal with
unmanaged resources. Bear in mind that by the time *your* finalizer
runs, the StreamWriter's finalizer may already have run. It sounds
like you may well not want a finalizer at all (they should be very
rare - basically only when you have direct access to unmanaged
resources, eg handles).
Ok, I want a logging method where Trace isn't good enough (I want
formatted logs), so I will write the log as HTML or RTF. The log
should be accessible from any method, so it needs to be 'global', so
it'll be a static class. The static constructor will open the log
file. A WriteLine method will write to it, and flush, to ensure the
data it written in the event of a crash, so I can see what last
happened (slower, yes, I know, but speed isn't an issue). And
sometime before the program ends, the file should close.
Instead, you should implement IDisposable and tell the caller to call
Dispose.
Ok. I will make it use the IDospable interface, thus implementing a
Dispose method, which will call tw.Close(). I'll see if that works.
The Close() call throws an exception saying I can't do this on a
closed file. But, I don't close it anywhere! Is the file
automatically closed by the destructor before I get a chance to use
it? Are resources' Dispose() auto-invoked or something? What's
strange is that the WriteLine doesn't throw an exception (although its
contents never make it to the file).

The underlying stream has probably had its finalizer run already.
(Note that this is separate from a Dispose method. Often, and using
MS's pattern, a finalizer will call Dispose, but that's just a matter
of implementation, not something the CLR does for you.)
Yes, I am vaguely aware of th differences between finalizer (which I
call a d'tor, I hate that C# has c'tors and doesn't use the same term
d'tor), and the Dispose method. Thanks for the explanation.

Zytan

Mar 22 '07 #7
Jon, writers do not have a Finalize method. The underlying streams
have Finalize methods to close themselves. The result is that the
writer's buffer is never flushed to the stream before the stream is
closed, resulting in lost data (it's designed this way). I assume
WriteLine executes error free because no attempt is made to flush to
the closed stream.
I see.
Zytan, avoid Finalizers for unmanaged code because stuff like this
happens. Try a syntax like:
using (StreamWriter stream = new FileInfo(@"c:\t est123").Create Text())
{
stream.WriteLin e("blah blah blah");
}
Yes, I know all about the using statement, and it's nice, and yeah, I
suppose it indicates that the TextWriter must have a Dispose, since it
forces it to be called, doesn't it? The problem is, is that this is
for logging. The file must close only after I am 100% certain that no
more calls to the static class's methods will be made (to log more
data).

Zytan

Mar 22 '07 #8
No. The error occurs because calling close in the TextWriter flushes
it's buffer to the stream, which may have been finalized. You can
close the stream multiple times with no exception. For instance

tw.Close();
tw.Close();
tw.Close();

is perfectly legit.
So, the TextWriter has not finalized, but the StreamWriter it wrap
has?

I admit I was a little confused with the whole:
StreamWriter sw = new StreamWriter(fi lename);
tw = TextWriter.Sync hronized(sw);

I was hoping that calling
tw.Close();
was all that I had to do, thinking, I was, in effect, calling
sw.Close();

But, apparantly, these are still two distinct objects, even though one
claims to wrap the other.

Zytan

Mar 22 '07 #9
Instead, you should implement IDisposable and tell the caller to call
Dispose.

Ok. I will make it use the IDisposable interface, thus implementing a
Dispose method, which will call tw.Close(). I'll see if that works.
(Let me fix that spelling: IDisposable)

Just as I suspected:
System.IDisposa ble': static classes cannot implement interfaces

Damn. Static c'tors exist, why not static d'tors? Is there anyway I
can hack one in?

Zytan

Mar 22 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
1827
by: D | last post by:
I have a winforms app that I'm reading some records from a datareader and writing them out to a file like so SqlDataReader dataReader = sqlCommand.ExecuteReader(); TextWriter textWriter = new StreamWriter(strFileName); while(drReader.Read()) { strRecord = ////// strRecord building stuff here textWriter.WriteLine(strRecord); iRecordCount++;
2
7153
by: kengtung | last post by:
Greetings all, I just started programming with C# (.Net FW 1.1) last year and still learning. Previously I am using VB 6.0. Recently, in one application, I encountered a C# error "Cannot write to a closed TextWriter.". I looked at the code and it looks ok to me. Maybe I am missing some understanding here on the inner function of TextWriter. Any information is much appreciated.
0
8752
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9257
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9174
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
6702
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6011
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4782
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3221
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2634
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2157
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.