2014-01-10 2 views
0

Я не могу поверить, что этого не задавали раньше, но я не могу найти ссылку здесь. Извините, если я пропустил это! Там есть много обновлений rtb.Text из потока, но мало или вообще нет при получении rtb.Text.Get richtextbox.text from thether thread

Мне нужно получить текстовое значение из richtextbox в потоке пользовательского интерфейса из другого потока, а затем получить возможность прокручивать каждую строку одного и того же richtextbox.

Я предполагаю, что приглашения и делегаты необходимы, но как их создать?

В качестве примера код, если он был в том же потоке, было бы что-то вроде:

private void checkRtbEntries() 
{ 
    if (rtb.Text != "") 
    { 
     foreach (string textLine in rtb.Lines) 
     { 
      // do some things in the background thread 
      // based on the rtb line content... 
     } 
    } 
} 

Но, checkRtbEntries() вызывается внутри потока BackgroundWorker и RTB в потоке пользовательского интерфейса, поэтому вызывается операция Cross-thread.

Любая помощь или указатели будут оценены.

+0

Просто из быстрого поиска: «C# cross thread получить контрольное значение» ... это аналогичный вопрос, но другой контроль. Найдите ответ: http://stackoverflow.com/questions/18086676/cross-thread-operation-is-not-valid-exception-when-trying-to-get-value-of-comb – HABJAN

+0

Спасибо, я не заметил этого, может быть, когда я искал проблему, а не сообщение об ошибке. Кажется, это немного перебор. Должен быть более простой способ? – gaw

ответ

3

При запуске BackgroundWorker нить, у вас есть возможность прохождения в них аргумент, который другой поток может ссылаться и использовать:

myWorker.RunWorkerAsync(rtb.Text); 

Внутри DoWork случае, отлитый аргумент обратно в строку и выполнять свои действия на нем.

var myRtbText = e.Argument.ToString(); 

Таким образом, ваша фоновая нить никогда не затрагивает нить пользовательского интерфейса.

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

Поскольку у вас нет ссылки на RichTextBox в DoWork случае (только содержание его имущества Text), вы не можете на самом деле назвать Lines свойство на оригинальном текстовом поле.

Вы должны иметь возможность имитировать его довольно легко (фактические тесты свойств для «\ r», «\ r \ n» и «\ n», но Environment.NewLine должны позаботиться о том, чтобы понять это для вас):

var allLines 
    = myRtbText.Split(new[] {Environment.NewLine}, StringSplitOptions.None); 

(Или используйте StringSplitOptions.RemoveEmptyEntries, если вы хотите игнорировать пустые строки)

+0

Спасибо, но пока это может быть полезно, иногда я не думаю, что это позволит работать 'foreach (string textLine в rtb.Lines)'. Или я чего-то не хватает? – gaw

+0

Внутри вашего DoWork события, вы будете делать 'foreach (строка textLine в myRtbText) {...}; ' –

+0

-1: вы не можете изменять элементы пользовательского интерфейса из фонового потока. – Idov

1

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

.
private delegate void checkRichTextBoxDelegate(); 
private void checkRtbEntries() 
{ 
    if (this.rtb.InvokeRequired) 
    { 
     checkRichTextBoxDelegate checkEntries = new checkRichTextBoxDelegate(checkRtbEntries); 
     this.Invoke(checkRtbEntries); 
    } 
    else 
    { 
     .... do your work on the RichTextBox, you are on the UI thread 
    } 
} 
+0

Спасибо за вашу запись, но я не хочу работать над RichTextBox. Я отредактировал свой вопрос, чтобы отразить, что работа в цикле должна быть в потоке Backgroundworker на основе записей в RichTextBox (если это имеет смысл?) – gaw