Поток должен использовать метод Invoke для доступа к элементам управления пользовательского интерфейса, а BackGroundworker - нет. Почему?

1

BackgroundWorker может напрямую обращаться к элементам управления пользовательского интерфейса, но Thread не может, почему?

Разве BackgroundWorker не является потоком? Если это не так, то что это? Кроме того, почему прямой доступ ограничен? Ограничивает ли прямой доступ Microsoft выбрала способ сделать что-то или сделать это так?

Теги:
multithreading
backgroundworker
difference

2 ответа

2

Согласно MSDN, "класс BackgroundWorker позволяет запускать операцию по отдельному выделенному потоку".

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

Также из MSDN: "Вы можете прослушивать события, сообщающие о ходе вашей работы и сигнале, когда ваша операция будет завершена". Это означает, что фоновое действие выполняется в отдельном потоке, и вы не можете получить доступ к графическому интерфейсу из этого потока. Но вы можете получить доступ к элементам управления графическим интерфейсом из события выполнения, потому что он поднят в основном потоке пользовательского интерфейса. Всякий раз, когда вы вызываете BackgroundWorker.ReportProgress() в рабочем потоке, он вызывает событие BackgroundWorker.ProgressChanged в основном потоке.

Кроме того, вы спрашиваете, почему GUI не может быть доступен из других потоков. Это связано с тем, что вся подсистема Windows GUI не является потокобезопасной. Насколько я знаю, это довольно нормально на других платформах (вне Windows), поэтому это определенно не относится к Microsoft. Вероятно, это связано с историческими причинами и, вероятно, имеет какое-то отношение к эффективности кода. (Потоковый безопасный графический интерфейс будет медленнее.) Но я не могу предоставить какой-либо сильный источник информации в качестве ссылки.

  • 1
    Он использует SynchronizationContext.Post (), поэтому он все еще работает в WPF.
  • 0
    @AlKepp Я правильно понимаю? Без использования Backgroundworker я должен определить делегаты метода для каждого возможного изменения свойства? Это безумие! Есть ли более простой способ сделать это без использования Backgroundworker?
Показать ещё 1 комментарий
-1

Фоновый работник будет генерировать исключение перекрестного потока, как и новый поток. Фоновый работник - просто причудливый способ начать новый поток.

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

Дополнительная информация о фоновых работниках: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.100).aspx

  • 0
    Я бы не назвал это «некой магией .NET», это просто вызов Invoke.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню