Приложение C # GUI, другой класс из другого потока, обновляющий интерфейс - PullRequest
4 голосов
/ 30 октября 2010

Я около недели изучал, как это сделать, и до сих пор не уверен в правильном подходе. В некоторых примерах я вижу, что в других используется класс Thread. Я вижу, что используется Invoke, что меня смутило.ставка.

У меня есть программа с графическим интерфейсом на c #, которая содержит текстовое поле, которое будет использоваться для предоставления информации пользователю.

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

С наилучшими пожеланиями!

Ответы [ 3 ]

8 голосов
/ 30 октября 2010

Легко:

MainWindow.myInstance.Dispatcher.BeginInvoke(new Action(delegate() {MainWindow.myInstance.myTextBox.Text = "some text";});

WHERE MainWindow.myInstance - это открытая статическая переменная, установленная на экземпляр MainWindow (должна быть установлена ​​в конструкторе и будет нулевой, пока экземпляр не будет создан).

Хорошо, это много в одной строке, позвольте мне перейти по этому вопросу:

Когда вы хотите обновить элемент управления пользовательского интерфейса, вы, как вы говорите, должны сделать это из потока пользовательского интерфейса. Существует способ передачи делегата (метода) в поток пользовательского интерфейса: Dispatcher. Я использовал MainWindow.myInstance, который (как и все компоненты пользовательского интерфейса) содержит ссылку на Dispatcher - вы можете альтернативно сохранить ссылку на Dispatcher в своей собственной переменной:

Dispatcher uiDispatcher = MainWindow.myInstance.Dispatcher;

Получив Dispatcher, вы можете либо Invoke () из BeginInvoke () передать делегат для запуска в потоке пользовательского интерфейса. Единственное отличие заключается в том, что Invoke () будет возвращаться только после запуска делегата (т. Е. В вашем случае был установлен текст TextBox), тогда как BeginInvoke () будет возвращаться немедленно, так что ваш другой поток, из которого вы вызываете, может продолжаться (Dispatcher будет работать как можно скорее, ваш делегат, который, скорее всего, сразу будет).

Я передал анонимного делегата выше:

delegate() {myTextBox.Text = "some text";}

Бит между {} является блоком метода. Это называется анонимным, потому что создается только один и у него нет имени, но я мог бы создать экземпляр делегата:

Action myDelegate = new Action(UpdateTextMethod);

void UpdateTextMethod() 
{
    myTextBox.Text = "new text";
}

Затем прошло это:

uiDispatcher.Invoke(myDelegate);

Я также использовал класс Action, который является встроенным делегатом, но вы могли бы создать свой собственный - вы можете прочитать больше о делегатах в MSDN, так как это немного не по теме.

0 голосов
/ 30 октября 2010

Просто используйте BackgroundWorker для того же. Это просто и избавляет от необходимости управлять своими собственными нитями. для более, вы можете увидеть: http://dotnetperls.com/backgroundworker

0 голосов
/ 30 октября 2010

Звучит так, как будто вы используете фоновый поток для обработки, но хотите, чтобы интерфейс реагировал? BackgroundWorker звучит как билет:

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

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