1

Whats the best way to run a function that syntax highlights text in a text box (left of = is red, right of = is blue). I ask because I had the data retrival in a CommandTask thread, and then did the highlighting in the FinishCommand (in UI thread) and that seemed to work but would deadlock the UI for a bit while it chugged away highlighting.

So, then I tried placing the highlighting code in a specalized RichTextBox Invoke function (thus thread safe) and moved the function call in the thread. That also worked, but for some reason was consistantly 4-8 seconds slower; this makes no sense to me because its the exact same code.

Finally, I tried making a temp RichTextBox in the thread, pasting the resulting text to it and highlighting. Then, all the Invoke function did was pass along the RTF to the real RichTextBox, but in this case for some reason the RTF isn't quite right, its the color gets shifted by 2 each time Ex: R=red, B=Blue, X=Black chars

Line 1. RRRRXBBBB (correct)

Line 2. XXRRRRBBB (coloring shifted 2 to the right)

Line 3. XXXXRRRRX (shifted 4 to the right, and so on)

So, my overarching question is which approach is best, why is threading the exact same code slower, and if approach 3 is the best, whats up with that wierd color shifting. Thanks!

Hershizer33
  • 1,206
  • 2
  • 23
  • 46

2 Answers2

3

It is slower because invoking is expensive. It requires two thread context switches and the UI thread has to be idle. Do this for every single highlighting change and you'll seriously bog down the thread. Using BeginInvoke() would fix that, but now you'll bog down the UI thread so it gets unresponsive. In other words, you can't win with that strategy.

Not sure what's going wrong with the helper RTB. It is off by two for each line, smells like a simple bug. Like not accounting for a carriage return + line feed at the end of the line.

A better way to speed this up is to tell the RTB to not update itself when you're busy highlighting text. Very big difference. That's not built-in but you can easily add it. And consider cutting your losses, RTB is just not a very good editor. Look at ScintillaNET.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Well, what about the 3rd case? The thread returns an RTF string and just writes it to the RichTextBox, which requires no Invoke (because the onFinish takes place in the UI thread). Even in that case its still about 3-6 seconds slower (also I fixed that shifting bug, had to do with the fact that /r/n is considered 1 char but is 2 bytes, thus throwing off the rtf string, just replaced all /r/n with /r/r and its fine) – Hershizer33 Aug 04 '11 at 19:26
  • I dunno, you are asking me to take a guess at code I cannot see. RTB can be slow when you pump a big chunk of RTF into it since it has to re-parse it. – Hans Passant Aug 04 '11 at 19:41
  • Good point, Ill scrounge together some relevent code and Pastebin it – Hershizer33 Aug 04 '11 at 20:15
0

A typical approach is to implement some kind of RTF generator that builds an RTF-compatible string using fast string manipulation (StringBuilder, StringWriter, etc), and then replace the RichTextBox control's RTF code with your own:

string rtf = /* Generate RTF code based on original text */
richTextBox.Rtf = rtf; // Replace text box's RTF code

You can find documentation on the RTF format here:

http://msdn.microsoft.com/en-us/library/aa140277%28v=office.10%29.aspx

You'll basically need to generate:

  • RTF Header
  • Font Table
  • Color Table
  • Character Text

You can do this through trial-and-error by using Wordpad, create a simple document with the syntax highlighting you desire, save the document in RTF format, and then open it in Notepad or similar application and then analyze the RTF generated.

Benefit of this method is that you can generate the RTF code in a separate thread and then update the user interface only once when the code is generated.

Chris Hutchinson
  • 9,082
  • 3
  • 27
  • 33