как обновить графический интерфейс Windows из другого класса? - PullRequest
4 голосов
/ 12 июля 2010

как вы обновляете элемент управления win формами (например, метка, индикатор выполнения) из другого класса, который создал графический интерфейс, но не создал поток?(например, обработчик события Program.cs)

Я нашел несколько сообщений об обновлении GUI из другого потока с помощью метода Invoke (), но то, что я нашел до сих пор, работает, только если кодызаписано в том же классе, что и форма

http://www.yoda.arachsys.com/csharp/threads/winforms.shtml

Ответы [ 2 ]

8 голосов
/ 12 июля 2010

Вам необходимо вызвать метод Invoke в форме. Например:

private void someMethod() {
    myOtherForm.Invoke(new MethodInvoker(delegate() {
        // update things in myOtherForm here
    }));
}

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

5 голосов
/ 12 июля 2010

Ну, здесь есть две отдельные проблемы:

  • Обновление интерфейса другого класса
  • Обновление интерфейса из другого потока

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

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

MethodInvoker action = () => form.StatusLabel.Text = "Finished";
form.BeginInvoke(action);

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

Label label = form.StatusLabel;
MethodInvoker action = () => label.Text = "Finished";
label.BeginInvoke(action);

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

(Я согласен с комментарием icktoofay о том, что BeginInvoke предпочтительнее, если только вам действительно не нужно ждать, между прочим ... хотя тогда вам нужно быть осторожным с изменениями любых переменных, захваченных анонимными функциями.)

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