Reputation: 14254
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.
Upvotes: 2
Views: 3195
Reputation: 22876
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);
Upvotes: 0
Reputation: 612
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.
Upvotes: 8
Reputation: 887857
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).
Upvotes: 0
Reputation: 84784
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:
new List<String>(maxLines)
RemoveRange
(0, excessCount)
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.
Upvotes: 0
Reputation: 947
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.
Upvotes: 0