Я прочитал много вводных статей о том, как обновлять основной интерфейс в фоновой теме, и большинство из них используют Control.Invoke и Control.BeginInvoke. Это хорошие решения, но есть две проблемы:
1. Вам нужно обратиться к System.Windows.Forms, а затем использовать System.Windows.Forms
2. Структура кода довольно запутанная. (На самом деле, это тоже вызвано #1)
Microsoft предлагает ещё одно более элегантное решение — System.Threading. SynchronizationContext。 Как видите, она не находится в namesapce System.Windows.Forms, так что мы можем справедливо использовать его в BusinessLaryer, Controler и даже в модулях.
И он очень удобен в использовании, вам нужно сосредоточиться только на следующих двух методах:
1. Отправить: отправляет запрос на обновление интерфейса в основной поток, блокируя текущий поток до его возвращения.
2. Пост: отправляет запрос на обновление интерфейса в основной поток без блокировки текущего потока.
На самом деле, все методы одинаковые, за исключением того, что send синхронен, а post — асинхронен
До появления Form1 form = new Form1(), объект SynchronizationContext был пустым, и при создании формы Form1 объект SynchronizationContext добавлялся в эту ветку. Так что ответ таков: когда создаётся объект Control,, объект SynchronizationContext также создаётся и прикрепляется к потоку. Всё это при использовании вида InitializeComponent(); После этого можно получить объект, который не является NULL
Наконец, разница между методами Sendt() и Post() в SynchronizationContext:
Send() реализуется простым вызовом делегата текущего потока (синхронный вызов). То есть поток пользовательского интерфейса вызывается непосредственно на подпотоке для выполнения, и подпоток продолжит выполнение после завершения выполнения потока пользовательского интерфейса.
Post() реализуется путем вызова делегата в пуле потоков (асинхронный вызов). Это связано с тем, что подпоток находит поток из пула потоков для настройки потока интерфейса, и подпоток напрямую выполняет свой собственный код, не дожидаясь завершения потока UI. Тестовый код:
Результат:
Основная тема интерфейса: 1 Тема: 5 SynchContext:1
Сводка:Объект SynchronizationContext в потоке пользовательского интерфейса, независимо от того, вызывается ли он в основном потоке или внутри потока, выполняется на основном, поэтому при многозатратном коде интерфейс интерфейса пользовательского интерфейса может зависнуть или сделать выгляд, что он умирает!
На самом делеПоток пользовательского интерфейса использует не класс SynchronizationContext, а WindowsFormsSynchronizationContextЭтот Дундон.
Исходный код System.Threading.SynchronizationContext:
Исходный код WindowsFormsSynchronizationContext:
|