Недопустимая операция между потоками: доступ к элементу управления из потока, отличного от потока, в котором он был создан - PullRequest
536 голосов
/ 27 сентября 2008

У меня есть сценарий. (Windows Forms, C #, .NET)

  1. Существует основная форма, в которой размещается пользовательский элемент управления.
  2. Пользовательский элемент управления выполняет некоторые тяжелые операции с данными, так что если я напрямую вызываю метод UserControl_Load, пользовательский интерфейс перестает отвечать на запросы при выполнении метода загрузки.
  3. Чтобы преодолеть это, я загружаю данные в другой поток (пытаясь как можно меньше изменить существующий код)
  4. Я использовал фоновый рабочий поток, который будет загружать данные и по окончании уведомлять приложение о том, что оно выполнило свою работу.
  5. Теперь появилась настоящая проблема. Весь пользовательский интерфейс (основная форма и ее дочерние элементы управления) был создан в основном основном потоке. В методе LOAD пользовательского контроля я выбираю данные, основанные на значениях некоторого элемента управления (например, текстового поля) в userControl.

Псевдокод будет выглядеть так:

КОД 1

UserContrl1_LoadDataMethod()
{
    if (textbox1.text == "MyName") // This gives exception
    {
        //Load data corresponding to "MyName".
        //Populate a globale variable List<string> which will be binded to grid at some later stage.
    }
}

Исключение, которое он дал, было

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

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

КОД 2

UserContrl1_LoadDataMethod()
{
    if (InvokeRequired) // Line #1
    {
        this.Invoke(new MethodInvoker(UserContrl1_LoadDataMethod));
        return;
    }

    if (textbox1.text == "MyName") // Now it wont give an exception
    {
    //Load data correspondin to "MyName"
        //Populate a globale variable List<string> which will be binded to grid at some later stage
    }
}

НО НО ... кажется, я вернулся к исходной точке. Приложение снова стать неотзывчивым Кажется, это связано с выполнением строки # 1, если условие. Задача загрузки снова выполняется родительским потоком, а не третьим, который я породил.

Я не знаю, понял ли я это правильно или неправильно. Я новичок в потоках.

Как мне решить эту проблему, а также каков эффект выполнения строки # 1, если блок?

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

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

Ответы [ 21 ]

0 голосов
/ 17 декабря 2017

Действие у; // объявлено внутри класса

label1.Invoke (у = () => Label1.Text = "текст");

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...