Control.Refresh () между потоками - PullRequest
0 голосов
/ 05 марта 2009

ОК, пожалуйста, не обращайте внимания на то, что было раньше. Я больше не получаю сообщения об ошибках, поэтому, похоже, моя проблема в том, чтобы заставить Диаграмму обновляться при изменении значений, для которых Диаграмма привязана к данным.

// Здесь не учитывается

Привет всем. У меня есть приложение WinForms с панелью panel1. Фоновый поток создает некоторые другие элементы управления, которые затем добавляются в panel1, например,

panel1.Controls.AddRange(myArrayOfControls);

Это прекрасно работает, и я вижу, как добавляются мои элементы управления. Но когда новые данные поступают в другой поток, я обновляю значения в родительских объектах элементов управления, а затем мне нужно Refresh(), чтобы дисплей обновлялся новыми значениями. Вызов Refresh() в любом контексте, поток, в который поступают данные, или объекты, которые получают обновленные данные, вызывают исключение InvalidOperation, поскольку требуется Invoke. Я пытался использовать Invoke в своих объектах модели, а также в потоке, куда поступают данные, и, похоже, не может избавиться от ошибки.

Если у кого-то есть руководство, я буду очень признателен.

ОБНОВЛЕНИЕ: Вот немного больше информации. Я не думал, что это потребует этого, но я был неправ. :)

У меня есть объектный класс MyObject. Этот класс MyObject создается в потоке с именем topologyThread. Данные поступают на dataThread. Экземпляры MyObject имеют переменную экземпляра Panel, а Panel имеет дочерние элементы управления, включая две диаграммы из пространства имен System.Windows.Forms.DataVisualization.Charting. Поэтому, когда данные поступают в dataThread, я обновляю соответствующие значения данных в объектах MyObject, а затем мне нужно обновить диаграммы, чтобы отобразить обновленные данные.

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

Ответы [ 3 ]

6 голосов
/ 05 марта 2009

Вы должны выполнить обе операции (обновить и обновить родительский объект элемента управления) из основного потока пользовательского интерфейса. Если вы изменяете элемент управления из фонового потока и не получаете исключение, это неудача, потому что это определенно ошибка.

Лучший способ сделать это - использовать

theControl.Invoke(new MethodInvoker(MyUpdateMethod));

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

1 голос
/ 05 марта 2009

JaredPar - довольно хороший ответ. Я хотел бы немного добавить к ней причину, по которой ваш код работает.

С помощью форм Windows вы можете общаться с потоком пользовательского интерфейса из других потоков. Это действительно плохая практика во всех случаях.

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

В этом и заключается ловкость прикосновения к пользовательскому интерфейсу из любого потока, кроме потока пользовательского интерфейса. Результат непоследователен, и поэтому очень плохая практика.

Боже, я бы хотел прокомментировать. :)

0 голосов
/ 05 марта 2009

Ответ ДжаредПара хорош. В некоторых случаях это может вызвать проблемы (в частности, когда метод вызывается до завершения построения формы) Вот несколько более надежная реализация (с использованием методов расширения)

public static class ControlInvokeExtensions
{
    public static void InvokeOnHostThread(Control host, MethodInvoker method)
    {
        if (IsHandleCreated)
            Invoke(new EventHandler(delegate { method(); }));
        else
            method();
    }
}

теперь вы можете называть это так

panel1.InvokeOnHostThread(() => panel1.Controls.AddRange(myArrayOfControls));

или если вы в форме:

InvokeOnHostThread(() => panel1.Controls.AddRange(myArrayOfControls));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...