Trace.Listeners.Add

Z

Zytan

According to http://www.15seconds.com/issue/020910.htm I am doing this
in the c'tor of a 'logfile' class:

objStream = new System.IO.FileStream(logFilename,
System.IO.FileMode.OpenOrCreate);
objTraceListener = new TextWriterTraceListener(objStream);
Trace.Listeners.Add(objTraceListener);

So, now all Debug.Write and Trace.Write get logged to the file. In
the d'tor I am doing:

Trace.Flush();
Trace.Listeners.Remove(objTraceListener);
objStream.Close();

(I added the Trace.Listeners.Remove part myself, since the tutorial
didn't mention it. Without Trace.Listeners.Remove, any calls to
Debug.Write will fail in the tutorial after the the stream is closed.)

But, in the d'tor, if I call Debug.Write or Trace.Write *before* the
above, it'll complain that I am writing to a closed file. It makes no
sense. If I run the debugger and step through it, it doesn't
complain, just as it shouldn't.

When / how do I close the file?

Zytan
 
G

Guest

Trace.Flush();
Trace.Listeners.Remove(objTraceListener);
objStream.Close();


When / how do I close the file?

Zytan

It is a bit hard to answer without seeing your source, but don't you need to
close objTraceListener instead of objStream? The next small example seems to
work properly:

class LogFile : IDisposable
{
private FileStream m_objStream;
private TextWriterTraceListener m_objTraceListener;
public LogFile(string logFilename)
{
m_objStream = new FileStream(logFilename, FileMode.Append);
m_objTraceListener = new TextWriterTraceListener(m_objStream) ;
Trace.Listeners.Add(m_objTraceListener) ;
}
public void Dispose()
{
m_objTraceListener.Flush();
Trace.Listeners.Remove(m_objTraceListener);
m_objTraceListener.Close();
}
}

FYI: tracing can be managed in the Web.config/App.config too. You don't need
to write any code then. See
http://msdn2.microsoft.com/en-us/library/1txedc80.aspx for details.

Kind regards,
Anne
 
Z

Zytan

It is a bit hard to answer without seeing your source, but don't you need to
close objTraceListener instead of objStream? The next small example seems to
work properly:

Well, my source is basically the source you have below. I really
don't know what I have to close or when. I see you are using
IDisposable. This is better than making a destructor (Finalize)?

Since my log needs formatting, I think I am going to implement my
own. I already have richtextbox functions, so I'll just make a
RichTextBox, and write to that, and output an .rtf file from it at the
end.

When should this code, that gets the rtf code from the RichTextBox and
writes it to a file, run? Should I make the class IDisposable, as you
did above? Or should I run it in a destructor? I guess this is a
different topic altogether. I just don't get what the difference is
between Dispose and Finalize.

Thanks, Anne

Zytan
 
Z

Zytan

When should this code, that gets the rtf code from the RichTextBox and
writes it to a file, run? Should I make the class IDisposable, as you
did above? Or should I run it in a destructor? I guess this is a
different topic altogether. I just don't get what the difference is
between Dispose and Finalize.

http://www.ondotnet.com/pub/a/dotnet/2002/02/11/csharp_traps.html
says under the 'Trap #2: Finalize versus Dispose' part:

"If you do handle precious unmanaged resources (such as file handles)
that you want to close and dispose of as quickly as possible, you
ought to implement the IDisposable interface. The IDisposable
interface requires its implementers to define one method, named
Dispose(), to perform whatever cleanup you consider to be crucial. The
availability of Dispose() is a way for your clients to say, "Don't
wait for the destructor to be called; do it right now.""

So, I assume by dealing with files, I am using unmanaged resources.

But, since NOW, I will not be writing to a file, but instead to a
RichTextBox, it doesn't really matter. I'll only write to the file
when the program is done, so I guess my question is different. I want
to know if I should make the open-write-close file code in Dispose?

I don't like my solution completely, since if the program crashed, and
then I get no logging data (it's still all in the RichTextBox), so
it's not perfect. If there was a RTF format that just allowed
appending without reconfiguring the entire file each time, this would
be a lot easier. I could implement this myself (writing actual RTF
code manually), but then i'm getting my hands dirty when the NET
framework is supposed to do this for me. Maybe that's the best way
for a simple log file:

http://www.gamedev.net/reference/programming/features/rtflog/

Zytan
 
Z

Zytan

I'll only write to the file
when the program is done, so I guess my question is different. I want
to know if I should make the open-write-close file code in Dispose?

I don't see any reason I should. IDisposable is so I can call Dispose
explicitly to release a resource, right? And I don't have to do
this. I just want the GC to run the destructor (Finalize) whenever it
wants to. At this time, the RichTextBox's RTF codes will be witten to
a file via open-write-close. That's proper, right?

Zytan

P.S. Do C#'ers use 'destructors' or 'finalizers'? What's the proper
term? If we use constructor, it seems that destructor should be ok.
 
Z

Zytan

The Finalizer (C++'s destructor) is private and it can only called by the
GC: by this you don't know when the Finalizer is called.
The Dispose() is public and it can only be called by your code (not by the
GC): by this you know when Dispose() is called.

So, that's the main thing. Dispose is when you want to 'dispose' or
sort of destruct (but not really, it's really just a 'shutdown' phase,
but the GC ultimately destructs it) your object when you decide, not
when the GC decides.
So both have their advantages and disadvantages. Combining both the
Finalizer and Dispose using the the "dispose pattern" is probably the best
way if you are dealing with unmanged resources (seehttp://www.codeproject.com/useritems/idisposable.aspfor some examples).

Ok, I'll take a look.
One big advantage of contracting your class to IDisposable is that you can
use the using statement which "implements" a hidden try..finally block and
calls Dispose() for you. For example I can use it with the class from my
previous message:

Right, so this way, not only can I call Dispose on my own terms, but
using 'using' I can actually force it to be called without even typing
it in. I now get why the using-statment is the way it is. It's just
a quicker (less error prone) way of forcing your object to shutdown
(close files, etc) immediately after the resource is finished being
used.

Thanks, Anne

Zytan
 

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

Similar Threads


Top