I know this is an old thread but if someone passed by he could have a hint.
Use the underlying FileStream directly without streamwriter wrapper. And use the follwing method to writeline.
public static void writeLine(FileStream stream, string str)
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
byte[] byteArray = encoding.GetBytes(str+"\r\n");
stream.Write(byteArray, 0, byteArray.Length);
}
You should aware of error handling. After a specific interval (every 10 or 20 minutes) you can use FileStream.Flush method.
Zytan wrote:
Ok, thought so, thanks.Zytan
28-Mar-07
Ok, thought so, thanks
Zytan
Previous Posts In This Thread:
TextWriter fails on Close() call in destructor
I have a log class that makes a synchronized TextWriter like so, i
the constructor
StreamWriter sw = new StreamWriter(filename)
tw = TextWriter.Synchronized(sw)
In the destructor, ~MyLogClass(), I call
tw.WriteLine("some stuff")
tw.Close()
The Close() call throws an exception saying I can't do this on
closed file. But, I don't close it anywhere! Is the fil
automatically closed by the destructor before I get a chance to us
it? Are resources' Dispose() auto-invoked or something? What'
strange is that the WriteLine doesn't throw an exception (although it
contents never make it to the file)
Zytan
Re: TextWriter fails on Close() call in destructor
That's not a good idea to start with. Finalizers should only deal wit
unmanaged resources. Bear in mind that by the time *your* finalize
runs, the StreamWriter's finalizer may already have run. It sound
like you may well not want a finalizer at all (they should be ver
rare - basically only when you have direct access to unmanage
resources, eg handles)
Instead, you should implement IDisposable and tell the caller to cal
Dispose
The underlying stream has probably had its finalizer run already
(Note that this is separate from a Dispose method. Often, and usin
MS's pattern, a finalizer will call Dispose, but that's just a matte
of implementation, not something the CLR does for you.
Jon
Jon, writers do not have a Finalize method.
Jon, writers do not have a Finalize method. The underlying stream
have Finalize methods to close themselves. The result is that th
writer's buffer is never flushed to the stream before the stream i
closed, resulting in lost data (it's designed this way). I assum
WriteLine executes error free because no attempt is made to flush t
the closed stream
Zytan, avoid Finalizers for unmanaged code because stuff like thi
happens. Try a syntax like
using (StreamWriter stream = new FileInfo(@"c:\test123").CreateText()
stream.WriteLine("blah blah blah")
}
Re: TextWriter fails on Close() call in destructor
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 - <
[email protected]
http://www.pobox.com/~skeet Blog:
http://www.msmvps.com/jon.skee
If replying to the group, please do not mail me too
No.
No. The error occurs because calling close in the TextWriter flushe
it's buffer to the stream, which may have been finalized. You ca
close the stream multiple times with no exception. For instanc
tw.Close()
tw.Close()
tw.Close()
is perfectly legit.
Re: TextWriter fails on Close() call in destructor
Ah, I see. Thanks for correcting me. I really should read mor
carefully :
-
http://www.pobox.com/~skeet Blog:
http://www.msmvps.com/jon.skee
If replying to the group, please do not mail me too
Ok, I want a logging method where Trace isn't good enough (I wantformatted
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.
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.
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
I see.
I see.
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
So, the TextWriter has not finalized, but the StreamWriter it wraphas?
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(filename);
tw = TextWriter.Synchronized(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
Re: TextWriter fails on Close() call in destructor
(Let me fix that spelling: IDisposable)
Just as I suspected:
System.IDisposable': static classes cannot implement interfaces
Damn. Static c'tors exist, why not static d'tors? Is there anyway I
can hack one in?
Zytan
Wait, since I'm just writing text to it, and want to format the HTMLor RTF
Wait, since I'm just writing text to it, and want to format the HTML
or RTF myself (RichTextBox is sloooooooow since it reformats on each
AppendText, and with the nature of logging, it's difficult to group up
a bunch of messages all at once to write in one go), then Trace is
fine, as I can write any text I want to it. I'll have a peak at using
System.Diagnostic.Trace again. I think this is the solution.
Back to the basics.
Zytan
Re: TextWriter fails on Close() call in destructor
Actually, in C++, there exists finalizers and destructors:
class classname {
~classname() {} // destructor
!classname() {} // finalizer
};
So, the distinction is necessary.
Zytan
I tried making a hack of a static destructor (by making the class non-static,
I tried making a hack of a static destructor (by making the class non-
static, and making a static variable that is an instance of the class,
thus, the destructor will be called on it when it goes bye bye), and
even then, the same error occurs.
The underlying stream must be finalized before I get a chance to stab
at it.
Since I have this hack of a destructor call, by making the class non-
static, it means I can now try IDisposable, and implement Dispose.
I'll try that now.
Zytan
I have no idea how to make it call Dispose() automatically.
I have no idea how to make it call Dispose() automatically. Dispose()
is so that I can 'destruct' the object manually when I want, so this
really does nothing. The finalizer is auto called. It's just called
too late.
HOW can it be called on an object, when I still have another variable
that is alive which wraps it? I need to get rid of the wrapper, I
think, and deal with it directly.
(Since the wrapper provides thread safety, I'll have to implement that
myself.)
Zytan
Re: TextWriter fails on Close() call in destructor
No. Neither of them has.
So, there are four objects involved:
1) Yours - with a finalizer
2) The original StreamWriter - no finalizer
3) The TextWriter - no finalizer
4) The Stream underlying the StreamWriter - with a finalizer
Your finalizer was calling Close on the TextWriter, which was calling
Close on the StreamWriter, which was trying to flush its buffer - and
that's what was wrong.
Yes, you are - the call will be propagated.
They're still two distinct objects, but the TextWriter has a reference
to the StreamWriter, and it just proxies calls onto the StreamWriter,
with appropriate synchronization.
--
Jon Skeet - <
[email protected]>
http://www.pobox.com/~skeet Blog:
http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Re: TextWriter fails on Close() call in destructor
Because classes are initialized, but never finalized.
No. I suggest you just flush your TextWriter after each call, and let
the OS close the handle automatically when the program exits.
--
Jon Skeet - <
[email protected]>
http://www.pobox.com/~skeet Blog:
http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Re: TextWriter fails on Close() call in destructor
What else could it do? You could have two objects with references to
each other, but no other references to them. *One* of them has to be
finalized before the other, doesn't it?
--
Jon Skeet - <
[email protected]>
http://www.pobox.com/~skeet Blog:
http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Re: TextWriter fails on Close() call in destructor
Zytan wrote:
The reason is that there is no finalizing dependency that tells the
memory management that one object has to be finalized before the other.
Because it's calling the finalizers after your main code has finished.
You can't predict when the objects will be finalized, so theoretically
the finalizer may be executed a long time after the main code has finished.
Why not make an object that works in two states? While the Page class
exists, the file is open, and in the Dispose method of the Page, call
Dispose on the object that will close the log file and change the state
of the object. Any writes to the object after that will be done by
opening the file, write the text and the close the file.
--
G?ran Andersson
_____
http://www.guffa.com
Ok, right, thanks for the clarification.
Ok, right, thanks for the clarification. It's hard to understand
everything when I am dealing with a wrapper of a wrapper of an object
I am not well versed in.
Please note that StreamWriter does have a finalizer:
http://msdn2.microsoft.com/en-us/library/aa328973(VS.71).aspx
StreamWriter.Finalize Method
And this page implies that TextWriter also has a finalizer:
http://msdn2.microsoft.com/en-us/library/ms227564.aspx
TextWriter.Dispose Method ()
"Always call Dispose before you release your last reference to the
TextWriter. Otherwise, the resources it is using will not be freed
until the garbage collector calls the TextWriter object's Finalize
method."
One question: Is it ok for me NOT to call .Close() or .Dispose() on
the StreamWriter or TextWriter, and let the GC do its work when the
application closes? Presumably, this will properly close the file, as
the GC does call the finalizer on both of them, which does the clea
up work
Right
Thanks again, Jon
Zytan
Re: TextWriter fails on Close() call in destructor
To be clear, you meant
"Because *static* classes are initialized, but never finalized.
But, why aren't they? I'd like to know the reasons why, although i
is futile, since it doesn't change reality
In Turbo Pascal, which the C# designer made, you could invoke a clea
up process on exit, which would be invoked in the 'stati
constructor', and thus have a 'static destructor'. I know you can d
something like this with the DomainUnload event, and I am assuming i
much the same thing. I fear, though, it doesn't help me, since m
underlying Stream will still be finalized before it ever gets called
I have not tested this, yet, though
I found a hack: Make the class non-static, instantiate an instanc
using a private instance c'tor within the static c'tor, thus th
finalizer will run. And I tried this, and still my Stream i
finalized before I get to poke at it. Besides, I hate hacks
The other 'hack', which is not so much a hack, is to use th
DomainUnload event, which I haven't yet tried
Zytan
Yes, true.
Yes, true
My point is: Can't it wait to clean my dinner plate until after I a
done eating
Zytan
Hm, but if we're both eating off each other's plates, and we arewaiting for
Hm, but if we're both eating off each other's plates, and we ar
waiting for each other to stab before we grab the last bite, the
there's a deadlock. I suppose the mother has to step in at thi
point
I don't believe this is the situation I've created, though
Zytan
Right.
Right. My object clean up code is just as likely to be run first a
another object's clean up code. I guess I was naively thinking the G
knew which object 'owned' which other object, and thus could guarante
that all of my objects exist until I am done myself
Right
Interesting solution, to open and append to the file if it is alread
closed
When would Dispose be called, though? I just want the logging file t
be open as long as possible
Zytan
Re: TextWriter fails on Close() call in destructor
Zytan wrote
I wouldn't depend on it, and certainly not when you've got potentia
buffer issues. For example, a buffer in StreamWriter might not b
flushed to the underlying stream, and if the underlying stream get
disposed first, then you lose the last bit of data you wrote. Not good
If it implements IDisposable, my general rule is: dispose of it
GC is for memory management, not resource management
It most likely makes a best-effort to flush its buffers to th
underlying stream, hoping against hope that the stream hasn't alread
been finalized
Read this too
http://msdn2.microsoft.com/en-us/library/ms172236(VS.80).asp
-- Barr
--
http://barrkel.blogspot.com/
Re: TextWriter fails on Close() call in destructor
Zytan wrote
It's easy to think of one's own code as special, but the finalizer you
wrote yourself is not treated differently from any other
There is no way that objects can own each other. They often reference
each other, which would cause a deadlock in the garbage collection if it
would consider the references. A Form object has a reference to a
ControlCollection, which contains a reference to a Control, which has a
reference back to the Form
Often things doesn't really make sense until you realise that the
alternatives make even less sense. :
It doesn't really matter. As long as you have the reference to the
object, it's not garbage collected. You can dispose at the end of the
Main method of your program
--
G?ran Andersso
____
http://www.guffa.com
Re: TextWriter fails on Close() call in destructor
No, I meant classes. Classes themselves are never finalized. Instances
of classes are finalized.
It's just not something that makes much sense - it would only be the
equivalent of adding a handler to the AppDomain unloading event, but
would be less deterministic.
Don't forget that while Anders designed C#, he didn't design .NET
itself, and as far as I'm aware (and I could well be wrong) there's no
idea of a static finalizer for types in the CLR.
Indeed.
I'm not sure whether it's guaranteed that DomainUnload will be
triggered before static members become eligible for garbage collection
- worth checking out.
I still prefer the idea of flushing the TextWriter after each call
though.
--
Jon Skeet - <
[email protected]>
http://www.pobox.com/~skeet Blog:
http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Re: TextWriter fails on Close() call in destructor
Interesting. Using Reflector, I can't find any evidence of a finalizer
on either TextWriter or StreamWriter. It's possible I'm missing
something, but it's also more than possible that MSDN is incorrect.
--
Jon Skeet - <
[email protected]>
http://www.pobox.com/~skeet Blog:
http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Re: TextWriter fails on Close() call in destructor
V1.1 StreamWriter had a finalizer, this one has been removed since V2.0.
Willy.
For my logger, I flush everything immediately after it is written, sothat the
For my logger, I flush everything immediately after it is written, so
that the log contains all possible information when a crash occurs, in
case the crash shuts down the app before all data can be flushed. So,
I am not worrying about flushing issues.
I agree. But this isn't a typical situation. I can't Dispose of my
object since the system has already finalized the underlying stream
that my Dispose method wants to use. It defeats the purpose. I wish
it would wait for me to dispose of my obects, and remove references to
them, before it finalizes them.
Maybe if I had direct access to the stream itself, it would wait? The
problem with wrappers (StreamWriter) is that I am not sure what it's
doing, and if that has any effect. I cannot see why a wrapper would
release a reference to an object when itself has not finalized, yet,
though. Somehow, the Stream just gets finalized.
Right.
Thanks, Barry. This is the relevant part:
"If neither of these solutions can be used (for example, if a
StreamWriter is stored in a static variable and you cannot easily run
code at the end of its lifetime), then calling Flush on the
StreamWriter after its last use or setting the AutoFlush property to
true before its first use should avoid this problem."
Which is what I do.
The only other possible solution is to have my finalizer REOPEN the
file, and do whatever it has to do with it (like writing EOF
terminators for that file type, like "</HTML>"), and then close it.
But, since I have nothing to write on close, all I have to do it
call .Close(). So, it's pointless.
You recommend that I dispose of the object, since the GC is for memory
management, not resources, but, the GC has already stepped in and
handled my resource for me!
Zytan
Oh, ok. Right.I guess I need something to be deterministic.
Oh, ok. Right.
I guess I need something to be deterministic. The problem with a
logger is that it is almost a part of the application overhead. Kind
of like how C++ ensures that the input and output streams are
guaranteed to be available, even though the language states that
(otherwise) there's no particular order chosen. But, this forced
stated makes everything work, since it just doesn't make sense to have
the streams initialized after your own code. And they work right
until the end, so destructors can write to the screen. This is what I
need. It looks like using Trace is the only option. Everything else
is a hack. Unfortunately with Trace, it makes it difficult to ALSO
display the log file onscreen at runtime.
Ok. And, it was a kind of 'hack' in Turbo Pascal, as well. It was
basically DomainUnload.
I really should check this out, yes.
Me, too. It's good enough, I think for what I need. I'll stick with
this.
As long as... TextWriter / StreamWriter is cleaned up propely without
a call to Close(). Considering the underlying Stream is already
finalized before I get a chance to call Close(), I think all is well.
Zytan
yup.Wow, i see, so this happens far more often than most (I) wouldrealize.
yup.
Wow, i see, so this happens far more often than most (I) would
realize.
I agree, I run into this all the time with programming. And it
catches even the smartest among us.
Yes, except in your Finalizer
My issue was that I wanted all my classes to have access to this
logger class, so I didn't want it to be an instance in the Main
method. If just Main used it, then none of these issues I raised
would even exist. I want all logging to occur at the source of the
problem, deep within the classes that know the most about what is
happened (or specifically, what went wrong).
Zytan
Re: TextWriter fails on Close() call in destructor
The problem is...
You were done eating. (the program was shutting down)
You had left the restaurant , and the bus boy was cleaning up.
Only THEN did you try to take another bite.
Can you really blame the bus boy????....I mean the door was locked
and you had gone home!!
If you really want to continue with this approach (as opposed to another
solution) Then I would Manually force a cleanup before exiting the
program.
static void Main()
{
try
{
Logger.Init(); //
Run Program
}
finally
{
Logger.Cleanup();
}
}
Or something like this
Bill
Have you considered opening and closing the file EVERY time you logsomething.
Have you considered opening and closing the file EVERY time you log
something.
I did something like this myself a few years ago.
It performed OK too.
Bill
Re: TextWriter fails on Close() call in destructor
Zytan wrote:
You can create an instance of it in the main method and use a static
method in the class for writing to the file. The static method can
determine if there is an active instance of the class or not, and use it
if it's there.
--
G?ran Andersson
_____
http://www.guffa.com
Re: TextWriter fails on Close() call in destructor
Zytan wrote:
You can create an instance of it in the main method and use a static
method in the class for writing to the file. The static method can
determine if there is an active instance of the class or not, and use it
if it's there.
--
G?ran Andersson
_____
http://www.guffa.com
Re: TextWriter fails on Close() call in destructor
Alternatively (and I should have pointed this out earlier) - use a
tried and tested logging library like Log4Net.
http://logging.apache.org/log4net/
--
Jon Skeet - <
[email protected]>
http://www.pobox.com/~skeet Blog:
http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Ok, thought so, thanks.Zytan
Ok, thought so, thanks.
Zytan
Submitted via EggHeadCafe - Software Developer Portal of Choice
Creating a WPF Custom Control
http://www.eggheadcafe.com/tutorial...9-c0b45fb68b78/creating-a-wpf-custom-con.aspx