Sending TraceSource output to TextBox

M

michael sorens

I want to send the output of a TraceSource to a TextBox on a WinForm.
I came up with this rudimentary approach but it does not seem terribly
efficient to close the StringWriter and get a new one each time I want to
output a chunk of tracing info. Further, I have to "manually" move the chunks
of data rather than having a pipeline, which would let each trace output line
flow into the TextBox as it occurs.

So I would welcome comments on two fronts:
(1) Is there a way to make the whole thing more automatic? That is, instead
of explicitly moving data as I have done, is there a way to set up a pipeline
connecting the output of the StringWriter to the TextBox?
(2) Failing the above, is there a cleaner/better way to implement what I
have shown below?

// initialize
strWriter = new StringWriter();
mySource.Listeners.Add(
new TextWriterTraceListener(strWriter, "TextBox"));

while (more to do) {

...do some output...

// process collected trace output into TextBox
StringReader strReader = new StringReader(strWriter.ToString());
string str = strReader.ReadLine();
while (str != null)
{
str = strReader.ReadLine();
diagTextBox.Text += str + Environment.NewLine;
}

// reset for next pass
strWriter.Close();
strWriter = new StringWriter();
((TextWriterTraceListener)mySource.Listeners["TextBox"]).Writer =
strWriter;
}
 
P

Peter Duniho

I want to send the output of a TraceSource to a TextBox on a WinForm.
I came up with this rudimentary approach but it does not seem terribly
efficient to close the StringWriter and get a new one each time I want to
output a chunk of tracing info. Further, I have to "manually" move the
chunks
of data rather than having a pipeline, which would let each trace output
line
flow into the TextBox as it occurs.

So I would welcome comments on two fronts:
(1) Is there a way to make the whole thing more automatic? That is,
instead
of explicitly moving data as I have done, is there a way to set up a
pipeline
connecting the output of the StringWriter to the TextBox?

Not built into .NET, that I am aware of. TextBoxBase only deals in
discrete changes to the text.
(2) Failing the above, is there a cleaner/better way to implement what I
have shown below?

Personally, I'd approach it by implementing my own TextWriter rather than
using the StringWriter. In your TextWriter, then you would just add new
text to the text box as it comes in.

In addition to avoiding the business of having to repeatedly create a
StringWriter, do some work, check the StringWriter, close it and create a
new one, it would also clean up the code by allowing all of the trace
listener stuff to be somewhere else rather than stuck in the middle of
your processing loop.

It would even make it easy to modify the code so that trace output was
buffered and/or properly marshaled over to the GUI thread. This latter is
important, because the code you posted appears to be doing time-consuming
work on the main GUI thread, which is not a good idea. That loop should
be executing on a different thread, with the Control.Invoke() or
Control.BeginInvoke() method used for updating the text box as necessary.

Finally note that you have a general performance problem with logging
trace information this way anyway. For relatively small amounts of text
(hundreds of lines) this is probably okay. But for every line of text you
add, you have to instantiate a whole new string and then copy it back to
the text box (I believe that internally the text box class does not use
the String class, so assigning to the Text property involves another copy
of the text, and possibly retrieving that property does as well).

In other words, as your text in the text box gets longer and longer, you
incur more and more overhead just to update it. This will eventually
bring the logging to a crawl. You can delay the inevitable by using a
StringBuilder or String[] to accumulate the text, assigning the current
value to the Text or Lines property, respectively. But the proportional
overhead will still exist.

The reason I bring that up is that if you are concerned about the kludgy
aspect of your current implementation, creating and closing and recreating
StringWriters and StringReaders over and over, perhaps this code is
important enough to warrant implementing some more robust visual logging
than just using the TextBox class. :) And actually, as long as you don't
have a need to interact with the text (select, copy, paste, etc.) it
wouldn't actually be that hard to write a custom control that displays an
arbitrary amount of text efficiently. Heck, you could even make that
custom control host a TraceListener that could be used to directly connect
it to the trace output. :)

Pete
 
M

michael sorens

Thanks for the commentary, Pete. You touched on some points there I had not
considered, and given me ideas on what I need to do from here.
 
S

Steven Cheng

Hi Michael,

I think there are two possible ways here to let you write trace to a
Textbox on winform:

1. Customize the TraceListener, you may inherit an existing one and
override its "Write" method so that for each message(to write into trace
log), you first send it to Textbox, then call the base class "Write" method.

2. Build a custom Stream class and this stream class will write into a
Textbox instead of file IO. Here is a web article demonstrate such means:

#Redirect I/O to a TextBoxWriter in .NET
http://www.codeguru.com/csharp/csharp/cs_data/streaming/article.php/c11777/

Also, if the thread your trace writing code executes is not the main UI
thread, you need to use Control.Invoke to ensure the winform UI specific
processing code is executed on main UI thread:

#WinForms UI Thread Invokes: An In-Depth Review of
Invoke/BeginInvoke/InvokeRequred
http://weblogs.asp.net/justin_rogers/articles/126345.aspx

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.


------------------------
From: =?Utf-8?B?bWljaGFlbCBzb3JlbnM=?= <[email protected]>
References: <[email protected]>
 

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