Разница между textbox и richtextbox в отношении потоков - PullRequest
0 голосов
/ 20 февраля 2019

Я столкнулся с проблемой, и я подумал, что это может быть из-за сложности моих классов, передающих объекты друг другу, поэтому я свел ее к минимуму, и проблема сохраняется:

У меня есть проект winform по умолчанию, созданный вСообщество VS2017

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

Я поместил следующий код в форму для заполнениятекстовые поля и запустить работника по нажатию кнопки:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        textBox1.Text = "Hello";
        richTextBox1.Text = "World!";
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (backgroundWorker1.IsBusy != true)
        {
            backgroundWorker1.RunWorkerAsync();
        }
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        MessageBox.Show(textBox1.Text);
        MessageBox.Show(richTextBox1.Text);
    }
}

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

textBox1.Text доступен из формы, такMessageBox показывает нормально.richTextBox1.Text НЕ доступен и выдает мне эту ошибку:

Операция с несколькими потоками недопустима: доступ к элементу управления richTextBox1 осуществляется из потока, отличного от потока, в котором он был создан.

ПОЧЕМУ?

Я предполагаю, что richTextBox имеет больше маршрутизации и переноса, но свойство .Text не совсем то же самое ?!Что здесь происходит?

РЕДАКТИРОВАТЬ: Я не думаю, что это дубликат отмеченного вопроса, потому что он не работал на TextBox.Text, в то время как мой работает.Я спрашиваю о различиях между свойствами TextBox и RichTextBox .Text.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Они были реализованы по-разному.

TextBox.Text в основном возвращает Control.Text, который вызывает WindowText, который использует GetWindowText.в комментариях к коду четко упоминается нормально вызывать кросс-поток GetWindowText. Поэтому они специально отключили проверку на кросс-поток, установив флаг inCrossThreadSafeCall.

Но дляReachTextBox.Text это не зависит от Control.Text. Он отправляет EM_STREAMOUT и использует результат.Таким образом, не было установлено никакого флага, кроме этого, из исключения для нескольких потоков.

Примечание: Вы должны игнорировать такие случаи и никогда не пытаться получить доступ к элементу пользовательского интерфейса из другого потока.Всегда используйте Invoke метод управления, когда вы пытаетесь взаимодействовать с потоком пользовательского интерфейса из другого потока.

0 голосов
/ 20 февраля 2019

Вы должны Invoke код пользовательского интерфейса (вы не можете запустить пользовательский интерфейс в потоке, отличном от пользовательского интерфейса):

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
   // What to do with UI
   Action action = () => {
      MessageBox.Show(textBox1.Text);
      MessageBox.Show(richTextBox1.Text);
   }

   if (InvokeRequired)  // We are in some background thread, Invoke required
     Invoke(action);
   else                 // We are in UI (main) thread, just call the action
     action(); 
}
...