Чтение большого количества символов и обновление текстового поля - PullRequest
2 голосов
/ 19 марта 2009

Я читаю данные из потока (предоставляемых процессом) посимвольно и добавляю их в текстовое поле, чтобы пользователь мог их видеть. Единственная проблема в том, что это SLOW . Пользователь должен видеть данные так, как они переданы программе (практически без задержки). Я хотел бы что-то вроде того, как терминалы обрабатывают текст, он может прокручиваться так быстро, что это размытие.

Как я могу улучшить это?

Для справки, я использую C # .net3.5 и winforms.

Ответы [ 3 ]

2 голосов
/ 19 марта 2009

Свойство Text текстового поля является строкой, и строки являются неизменяемыми (это означает, что вы не можете изменить строку). Это означает, что каждый раз, когда вы добавляете символ, вы будете создавать новую копию строки с одним символом, добавленным в конце.

Если, например, у вас есть 10000 символов в текстовом поле, вы скопируете 20 КБ данных для добавления следующего символа. Добавление ста символов по одному означает копирование 2 МБ данных.

Если данные основаны на строках, используйте список вместо текстового поля, чтобы обновлять последнюю строку нужно только при добавлении символа.

1 голос
/ 19 марта 2009

В многострочном текстовом поле вы получите немного лучшую производительность, используя Selection для добавления символов:

textBox1.Select(textLength, 0);
textBox1.Selectedtext = newText;
textLength += newText.Length;

Но, как вы можете видеть, вам придется отслеживать длину самостоятельно, и этот метод, вероятно, сломается, если вы разрешите контрольные символы (например, backspace).

Я бы порекомендовал Гуффе сначала использовать список.

0 голосов
/ 19 марта 2009

Некоторый код поможет выяснить, что является узким местом.

Тем не менее, я бы попробовал что-то в этом духе (я бы не советовал копировать / вставлять, поскольку я не могу проверить это здесь):

// Stream s...
byte[] buffer = new buffet[bufferSize];
s.BeginRead(b, 0, buffer.Length,
    delegate
        {
            if (textBox1.InvokeRequired)
            {
                textBox1.Invoke(
                    new MethodInvoker(
                        delegate 
                        { 
                            textBox1.Text = Encoding.Unicode.GetString(b); 
                        }));
            }
            else
            {
                textBox1.Text = Encoding.Unicode.GetString(b);
            }
         }, null);
...