TextWriter fails on Close() call in destructor

Z

Zytan

Alternatively (and I should have pointed this out earlier) - use a
tried and tested logging library like Log4Net.http://logging.apache.org/log4net/

I've ran across this before. I hate using other people's code. I'd
rather learn the language myself, and code it myself, this way, I
learn. And I can upgrade as I need to. But, yes, beyond a certain
point, I just gotta do what works. Letting the file close itself is
ok for me. I don't care that I can't write my </HTML> at the end.
(Which is something I couldn't do even if I opened/closed the file on
each log access, so no difference)

Zytan
 
Z

Zytan

Alternatively (and I should have pointed this out earlier) - use a
tried and tested logging library like Log4Net.http://logging.apache.org/log4net/

I've ran across this before. I hate using other people's code. I'd
rather learn the language myself, and code it myself, this way, I
learn. And I can upgrade as I need to. But, yes, beyond a certain
point, I just gotta do what works. Letting the file close itself is
ok for me. I don't care that I can't write my </HTML> at the end.
(Which is something I couldn't do even if I opened/closed the file on
each log access, so no difference)

Zytan
 
Z

Zytan

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();
}
}

The only problem is that not every class in the app can call
Logger.Write() like this.

Zytan
 
Z

Zytan

My issue was that I wanted all my classes to have access to this
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.

Yes, that's true. I guess I lied. Even in this case, the finalizer
is run before I can write out my last bit. But then again, I could
just reopen and append to the file. So, I guess this is good enough.

Thanks for all your help!

Zytan
 
B

Bill Butler

Zytan said:
The only problem is that not every class in the app can call
Logger.Write() like this.

Why not?
Logger.Write() could easily be a static method accessible from anywhere.


Bill
 
J

Jon Skeet [C# MVP]

Zytan said:
I've ran across this before. I hate using other people's code.

And yet you're using Microsoft's all the time. If you dismiss all third
party libraries, you'll end up reinventing a lot of wheels.
I'd rather learn the language myself, and code it myself, this way, I
learn.

Log4net is open source - so download the source and see how they do it.
 
Z

Zytan

I've ran across this before. I hate using other people's code.
And yet you're using Microsoft's all the time. If you dismiss all third
party libraries, you'll end up reinventing a lot of wheels.

I have no choice with Microsoft, and it is far, far more tested than
such 3rd party code. I don't think that's a fair comparison. In
general, open source software doesn't have great quality, from what
I've seen.

I agree reinventing the wheel is bad, in some ways. But, not in terms
of learning. Also, with your own code, you can fix it when things go
bad. Of course, with open source, you can do this, too.
Log4net is open source - so download the source and see how they do it.

Good idea. I would be interested in their ideas.

Thanks,

Zytan
 
Z

Zytan

The only problem is that not every class in the app can call
Why not?
Logger.Write() could easily be a static method accessible from anywhere.

Yes, that's true.

But, I guess this doesn't solve all problems, since still, the stream
finalizes before my class finalizes (someone mentioned that I didn't
'root' my stream deep enough, and that's why it's finalized before I
am done with it, but it's a static data member in the class -- how
much more rooted can it be?). So, the "cleaning up nicely" puspose
of the finalizer is defeated, since it's already cleaned up. Thus, I
don't need a finalizer. So, what is left is nothing different than
what I already have -- a pure static class.

If I find that I need to log something after the stream has closed,
I'll have redo the function to reopen the file and append, but, so
far, I don't.

Zytan
 
B

Barry Kelly

Zytan said:
This is what I have:

static class LogFile
{
private static TextWriter m_twSynch;
...
}

Isn't that rooted? How can I 'root' it more deeply?

Yes it is, until the final non-background thread exits.
Please tell me how I can root them! I believe I have been rooting
them, as you've suggested, all along.

The final thing I'd say is to be sure that you close up these log files
before your main thread exits - e.g. in the Main method, etc., or
similar for a hosted environment - e.g. in an implementation
IHttpModule.Dispose if it's a module in ASP.NET, or hooked to
HttpApplication.Disposed event, etc.

I can't be more specific on ASP.NET because most work I've done with it
was at a relatively low level, at the IHttpAsyncHandler level.

I suspect part of your problem is that whenever you're closing the log
files etc., it's too late. Where are you currently doing it?

-- Barry
 
Z

Zytan

static class LogFile
Yes it is, until the final non-background thread exits.
Ok.


The final thing I'd say is to be sure that you close up these log files
before your main thread exits - e.g. in the Main method, etc., or
similar for a hosted environment - e.g. in an implementation
IHttpModule.Dispose if it's a module in ASP.NET, or hooked to
HttpApplication.Disposed event, etc.

Well, just imagine that, inside of functions all over the place, there
are calls to LogClass.WriteLine() just as there are Debug.Assert() and
Debug.WriteLine() everywhere. So, where would I call
LogClass.CloseFile()? I suppose at the end of Main(). But, this
isn't my problem, really... if the system is closing the streams
itself, then I really don't have an issue with that. My only issue
was that my own finalizer wanted to say goodbye before it closed, but
it's too late. I know I can solve this by reopening & appending, but
I really don't need to say goodbyte, I'll just leave it closed. I'm
happy.
I suspect part of your problem is that whenever you're closing the log
files etc., it's too late. Where are you currently doing it?

Well, the only problem is that I wanted to write out </HTML> then
close the stream. But the stream is already closed by the time the
finalizer is run. Since I don't really care that </HTML> is there or
not, I'm not bothered by this.

But, if I really wanted this, I could make a LogClass.CloseFile()
method that Main() calls, and it could do this. Then I may run into
an issue of LogClass.WriteLine() being called in some class after this
happens (say, in its finalizer), so, even in that case, it's best just
to let the system clean up. There's no 100% sure fire way to write </
HTML> at the end after everyone is done, I think. Even if I used a
listener for Debug.Trace, I doubt there's a place I can run my
Trace.WriteLine("</HTML>") after everyone else is done with it, since,
as someone said, my code isn't special.

Thanks, Barry

Please no worries, my solution is fine for my need as is, now. I'll
let the system close the stream itself.

Zytan
 
J

Jon Skeet [C# MVP]

Zytan said:
I have no choice with Microsoft, and it is far, far more tested than
such 3rd party code. I don't think that's a fair comparison. In
general, open source software doesn't have great quality, from what
I've seen.

My experience is that the more popular projects have just as good
quality code as many commercial projects.

I've had very good experience with open source projects in general.
I agree reinventing the wheel is bad, in some ways. But, not in terms
of learning. Also, with your own code, you can fix it when things go
bad. Of course, with open source, you can do this, too.

You can both learn and fix with open source code...
Good idea. I would be interested in their ideas.

And then you can use it if it works, fix it if it doesn't, and save a
load of time...
 
J

james

Please note that StreamWriter does have a finalizer:
And this page implies that TextWriter also has a finalizer:
http://msdn2.microsoft.com/en-us/library/ms227564.aspx
TextWriter.Dispose Method ()

Okay dug around the IL for those classes (using ILDasm on
mscorlib.dll). In .Net2.0 there is NO Finalize method for
StreamWriter or TextWriter. In .Net1.1 there is a Finalize method for
StreamWriter only, but this does not flush any data. So microsoft is
wrong Im right :)

-James
 
Z

Zytan

Okay dug around the IL for those classes (using ILDasm on
mscorlib.dll). In .Net2.0 there is NO Finalize method for
StreamWriter or TextWriter. In .Net1.1 there is a Finalize method for
StreamWriter only, but this does not flush any data. So microsoft is
wrong Im right :)

Thanks, James.

Then I wonder what happens when they are already 'finalized' or
whatever by the time I get to them. Does the system ensure they are
flushed if it closes the stream itself? No matter, since I flush
after every write, anyway, just to be sure.

Zytan
 
J

james

Thanks, James.

Then I wonder what happens when they are already 'finalized' or
whatever by the time I get to them. Does the system ensure they are
flushed if it closes the stream itself? No matter, since I flush
after every write, anyway, just to be sure.

Zytan

If you don't close the writer it will not get flushed.
 
Z

Zytan

If you don't close the writer it will not get flushed.- Hide quoted text -

Ok, thought so, thanks.

Zytan
 
A

Ahmad Alshaalan

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top