G
Guest
Hello,
Sorry for the long-winded dissertation - but, I have an application where I
need to write text to a rich text box using a common method, callable from
anywhere in my application. The color of the text will depend upon the first
argument and the text will be contained in the second argumet. As far as I
know, my application is not multithreaded - at least I don't knowingly start
any other threads. Since I don't know what the heck I'm doing, I found an
application that did this type of thing and merely "borrowed" the code to do
it. The code is shown below, with a couple of changes, which I will describe.
My first question involves why the code is written using Invoke rather than
just a simple method call? I do know that Invoke should (must?) be used when
doing multithreading, but I wasn't aware I was doing any multithreading.
However, if I remove the Invoke "wrapper" from around the code it won't even
compile - so I left the "wrapper" in place!
Second, notice that I have a test for the msg parameter being null. This
should never happen but it sometimes does. I've single stepped through it
and sometimes, although msg is not null just prior to entering the Invoke
block, it mysteriously becomes null when that block is entered.
The next issue is the color. Note that I am setting the color with
parameter "msgtype". Most of the time this also works fine. However, once
in a while the parameter value and the font's color property are okay right
up to the rtfTerminal.AppendText statement. But as that statement gets
executed both the parameter and the font property change and the text gets
printed in the wrong color. Sometimes this change occurs in the middle of
the string that's being printed.
The final issue is the jitter that accompanies the ScrollToCaret() method if
the entire message is written as one string followed by a single call to
ScrollToCaret(). It makes no sense to me why doing it the way I have done -
character at a time - should work differently, but it does. I think this is
probably a separate issue from the previous two.
So, my final suspicion on this is that the code I "borrowed" probably has
some inherent philosophical problem that is currently beyond my knowledge.
Is there a more appropriate way to implement a common method to write to a
rich text box?
Thanks,
Ray
public void Log(LogMsgType msgtype, string msg)
{
rtfTerminal.Invoke(new EventHandler(delegate
{
rtfTerminal.SelectedText = string.Empty;
rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont,
FontStyle.Bold);
rtfTerminal.SelectionColor = LogMsgTypeColor[(int)msgtype];
rtfTerminal.Font = new Font(rtfTerminal.SelectionFont,
FontStyle.Bold);
if (msg != null)
{
// This loop prevents scrolling on every character, which causes
jitter.
foreach (char ch in msg)
{
if (ch != '\r')
{
rtfTerminal.AppendText(ch.ToString());
if (ch == '\n')
rtfTerminal.ScrollToCaret();
}
}
Application.DoEvents();
}
else
rtfTerminal.AppendText("\n\n**** ERROR: NULL MESSAGE ****\n\n");
}
));
}
Sorry for the long-winded dissertation - but, I have an application where I
need to write text to a rich text box using a common method, callable from
anywhere in my application. The color of the text will depend upon the first
argument and the text will be contained in the second argumet. As far as I
know, my application is not multithreaded - at least I don't knowingly start
any other threads. Since I don't know what the heck I'm doing, I found an
application that did this type of thing and merely "borrowed" the code to do
it. The code is shown below, with a couple of changes, which I will describe.
My first question involves why the code is written using Invoke rather than
just a simple method call? I do know that Invoke should (must?) be used when
doing multithreading, but I wasn't aware I was doing any multithreading.
However, if I remove the Invoke "wrapper" from around the code it won't even
compile - so I left the "wrapper" in place!
Second, notice that I have a test for the msg parameter being null. This
should never happen but it sometimes does. I've single stepped through it
and sometimes, although msg is not null just prior to entering the Invoke
block, it mysteriously becomes null when that block is entered.
The next issue is the color. Note that I am setting the color with
parameter "msgtype". Most of the time this also works fine. However, once
in a while the parameter value and the font's color property are okay right
up to the rtfTerminal.AppendText statement. But as that statement gets
executed both the parameter and the font property change and the text gets
printed in the wrong color. Sometimes this change occurs in the middle of
the string that's being printed.
The final issue is the jitter that accompanies the ScrollToCaret() method if
the entire message is written as one string followed by a single call to
ScrollToCaret(). It makes no sense to me why doing it the way I have done -
character at a time - should work differently, but it does. I think this is
probably a separate issue from the previous two.
So, my final suspicion on this is that the code I "borrowed" probably has
some inherent philosophical problem that is currently beyond my knowledge.
Is there a more appropriate way to implement a common method to write to a
rich text box?
Thanks,
Ray
public void Log(LogMsgType msgtype, string msg)
{
rtfTerminal.Invoke(new EventHandler(delegate
{
rtfTerminal.SelectedText = string.Empty;
rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont,
FontStyle.Bold);
rtfTerminal.SelectionColor = LogMsgTypeColor[(int)msgtype];
rtfTerminal.Font = new Font(rtfTerminal.SelectionFont,
FontStyle.Bold);
if (msg != null)
{
// This loop prevents scrolling on every character, which causes
jitter.
foreach (char ch in msg)
{
if (ch != '\r')
{
rtfTerminal.AppendText(ch.ToString());
if (ch == '\n')
rtfTerminal.ScrollToCaret();
}
}
Application.DoEvents();
}
else
rtfTerminal.AppendText("\n\n**** ERROR: NULL MESSAGE ****\n\n");
}
));
}