Как обновить RichTextBox из BackgroundWorker с помощью BeginInvoke - PullRequest
2 голосов
/ 24 января 2012

У меня есть небольшое приложение, которое читает файл с разделителями каналов и записывает строки в RTB, выделяя, если в определенных «столбцах» есть запрещенные символы. Это работает отлично ... однако, пользователи хотят, чтобы индикатор выполнения отображал написанные строки «вживую», а также чтобы можно было отменить их на полпути.

У меня есть следующий метод расширения, который я использовал для записи в RichTextBox, при блокировании пользовательского интерфейса, но это не помогает при использовании BackgroundWorker с BeginInvoke.

Ошибка при поиске текущей длины текста.

public static void AppendLine(this RichTextBox richTextBox, string text, List<Char> foundChars, List<int> columns)
        {
            var split = text.Trim().Split(new char[] { '|' });

            for (int i = 0; i < split.Count(); i++)
            {
                **var start = richTextBox.TextLength;**
                richTextBox.AppendText(split[i]);
                var end = richTextBox.TextLength;

                if (columns.Contains(i + 1))
                {
                    foreach (var foundChar in foundChars)
                    {
                        var current = start;

                        while (current > 0)
                        {
                            var position = richTextBox.Find(new char[] { foundChar }, current, end);
                            current = position + 1;
                            if (current > 0)
                            {
                                richTextBox.Select(position, 1);
                                richTextBox.SelectionColor = Color.Red;
                            }
                        }
                    }
                }
                richTextBox.SelectionLength = 0;
                richTextBox.SelectionColor = Color.Black;
            }
            richTextBox.AppendLine();
        }

private void UpdateResultsLine(string line, List<char> foundChars)
        {
            if (txtResults.InvokeRequired)
            {
                txtResults.BeginInvoke(new UpdateResultsLineDelegate(UpdateResultsLine), line, foundChars);
            }
            txtResults.AppendLine(line, foundChars, _fileType.ProcessColumns);
        }

Однако, если я называю любое / все эти расширения одним и тем же способом, они работают?

public static void AppendLine(this RichTextBox richTextBox)
{
    richTextBox.AppendText(Environment.NewLine);
}

public static void AppendLine(this RichTextBox richTextBox, string text)
{
    richTextBox.AppendText(text + Environment.NewLine);
}

public static void AppendLine(this RichTextBox richTextBox, string text, params object[] args)
{
    richTextBox.AppendLine(string.Format(text, args));
}

Чего мне не хватает? или есть другой способ записать цветной текст в RTB?

Ответы [ 2 ]

5 голосов
/ 24 января 2012

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

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null);
        else action.Invoke();
    }
 }

И когда и когда вы захотите обновить что-либо в пользовательском интерфейсе, вам просто нужно сделать

 richTextBox.Invoke(() => { richTextBox.AppendText(text + Environment.NewLine); });

Надеюсь, это работает для вас.

4 голосов
/ 24 января 2012

Вам нужен оператор else в вашем методе UpdateResultsLine.Когда требуется Invoke, вы выполняете метод UpdateResultsLine с использованием делегата (вызывая), но затем вызываете снова, не используя Invoke

Кроме того, почему вы используете BeginInvoke (асинхронно)и использовать Invoke (синхронизация)?Вы уверены, что у вас нет проблем с синхронизацией?Использование Invoke и добавление оператора else может решить ваши проблемы:

private void UpdateResultsLine(string line, List<char> foundChars)
{
    if (txtResults.InvokeRequired)
    {
        txtResults.Invoke(
            new UpdateResultsLineDelegate(UpdateResultsLine),
            line,
            foundChars);
    }
    else
    {
        txtResults.AppendLine(
            line,
            foundChars,
            _fileType.ProcessColumns);
    }
}
...