2010-11-21 3 views
4

У меня есть основной поток GUI с функцией XYZ(), чтобы что-то сделать с графическим интерфейсом. В другом потоке, если я вызываю XYZ() из дескриптора основного графического интерфейса пользователя, он отображает ошибку «Неверная операция поперечного потока: элемент управления Button00» доступен из потока, отличного от потока, на котором он был создан ».Вызов функции из другого потока в C#

Как это решить? Я думаю, мне нужно отправить сообщение в поток GUI для выполнения функции XYZ. Пожалуйста, помогите мне.

Спасибо.

Ankata

ответ

7

Причина вы получаете сообщение об ошибке, потому что вы пытаетесь обновить элемент управления GUI из другого потока, чем главное что не возможно. Элементы управления графическим интерфейсом всегда должны быть изменены в том же потоке, который использовался для их создания.

Вы можете использовать Invoke, если InvokeRequired, который будет маршировать вызов в основной теме. Вот nice article.

Но, вероятно, самым простым решением было бы просто использовать BackgroundWorker, потому что таким образом вам больше не нужно вручную направлять вызовы в поток графического интерфейса. Это делается автоматически:

var worker = new BackgroundWorker(); 
worker.DoWork += (sender, e) => 
{ 
    // call the XYZ function 
    e.Result = XYZ(); 
}; 
worker.RunWorkerCompleted += (sender, e) => 
{ 
    // use the result of the XYZ function: 
    var result = e.Result; 
    // Here you can safely manipulate the GUI controls 
}; 
worker.RunWorkerAsync(); 
+0

В моем коде: функция XYZ выполняет что-то и обрабатывает некоторый элемент управления графическим интерфейсом и помещается в основной класс формы. Я попробовал добавить ваш код справки в другой ад, чтобы вызвать функцию XYZ как mainForm.XYZ(), но это та же ошибка? – Ankata

+0

Таким образом, вам придется разделить обработку с обновлением элементов управления графическим интерфейсом на две отдельные функции. Таким образом, вы использовали бы первую функцию для выполнения дорогостоящей обработки в фоновом работнике, и когда она вернет результат, вы вызовете свою вторую функцию для обновления GUI. Если вы не разделите их, вы не сможете запустить его в другом потоке, потому что, как объясняется в моем ответе, элементы управления графическим интерфейсом могут быть обновлены только в основном потоке. –

+0

Однако это очень сложный код для обработки и обновления графического интерфейса. – Ankata

3

В общем GUI в C# можно обновить только из той же нити она была создана , если это не тот же поток, чем значение InvokeRequired верно еще это ложь, если это правда, что вы звоните снова тот же метод, но с той же нити графический интерфейс был создан

вы должны использовать его как это:

delegate void valueDelegate(string value); 

    private void SetValue(string value) 
    { 
     if (someControl.InvokeRequired) 
     { 
      someControl.Invoke(new valueDelegate(SetValue),value); 
     } 
     else 
     { 
      someControl.Text = value; 
     } 
    } 

Попробуйте для получения дополнительной информации

How to update the GUI from another thread in C#?

+0

Потому что есть много процессов до и после обновления многих элементов управления. Поэтому я не могу использовать метод делегата. Вы знаете, как отправить сообщение в другой поток, и он сам будет обрабатывать – Ankata

+0

Я не понимаю, почему вы не можете использовать делегат, вы уверены, что понимаете код выше? этот код просто проверяет, находитесь ли вы в потоке, который создает элемент управления, и если он не вызывает тот же метод из строгого потока, который вам незаметен, так что декларация делегата повлечет за собой проблему. – Delashmate

Смежные вопросы