2

I have a C# application in which a LOT of information is being added to a Textbox for display to the user. Upon processing of the data, almost immediately, the application becomes very slow and unresponsive. This is how I am currently attempting to handle this:

   var saLines = textBox1.Lines;
   var saNewLines = saLines.Skip(50);
   textBox1.Lines = saNewLines.ToArray();

This code is run from a timer every 100mS. Is there a better way to handle this? I am using Microsoft Visual C# 2008 Express Edition. Thanks.

1
  • Can you post example of information shown and code that does this? Commented Jan 13, 2010 at 16:04

5 Answers 5

8

The simple answer is TextBox.AppendText().

You get much better performance initially. I tested writing a 500 char message every 20 ms for 2 mins (with BackgroundWorker) and the UI remained responsive and CPU minimal. At some point, of course, it will become unresponsive but it was good enough for my needs.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. Some months later I was able to get this working by building up global StringBuilder objects in the backgroundWorker and then using TextBox.AppendText() in the backgroundWorkerReportProgress and backgroundWorkerRunWorkerCompleted methods.
Can't believe I didn't know this! I knew it must be slower doing it through other methods but the speed increase is great! And the textbox actual stays responsive.
0

Try by having in memory a list with the content, and removing the first 50 elements by RemoveRange and then going with ToArray(); Like this :

lst.RemoveRange(0,50);
textBox1.Lines = lst.ToArray();

It should be a lot faster.

Comments

0

I'd say your main problem here is that you are using the TextBox as your primary storage for your text. Everytime you call TextBox.Lines, the string is split on Environment.NewLine.

Try turning it around:

  • Store the text in a new List<String>(maxLines)
  • In your AddLine method, check the length of your text buffer and use RemoveRange(0, excessCount)
  • Update your display TextBox by calling String.Join(Environment.NewLine, textBuffer.ToArray())

That last call is a bit expensive, but it should stop your slowdowns. To get it any faster you'd need to use a statically sized string array and move the references around yourself.

Comments

0

The most efficient way to trim an array is to create a new array of the desired size, then use Array.Copy to copy the desired portion of the old array.


I would recommend that you maintain a List<string> containing all of your lines. You should use a StringBuilder to build a string containing the lines you're looking for, and set the textbox's Text proeprty to the StringBuilder's string. For added performance, set the StringBuilder's capacity to a reasonable guess of the final sie of the string. (Or to list.Skip(...).Take(...).Sum(s => s.Length))

If you're concerned about memory, you can trim the List<string> by calling RemoveRange.

As long as you don't put too much in the textbox at once, doing it this way should be extremely fast. All of the manipulation of the List<string> and the StringBuilder can be done in a background thread, and you can pass the completed string to the UI thread.

The TextBox.Lines property simply concatenates the array you give it using a StringBuilder, so there's no point in using it (and making a needless array).

Comments

0

Instead of splitting the text and then re-joining it, just get the sub-string from the 51st line:

int i = textBox1.GetFirstCharIndexFromLine(50);
if (i > 0) textBox1.Text = textBox1.Text.Substring(i);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.