В .NET память разделяется внутри домена приложений, что означает, что все потоки могут получить доступ ко всем данным.Итак, на самом деле вы управляете доступом к определенным битам данных из определенных потоков, чтобы они не мешали друг другу.
Invoke и BeginInvoke позволяют запускать код в потоке пользовательского интерфейса, которыйполезно, потому что элементы управления пользовательского интерфейса могут быть доступны только из потока пользовательского интерфейса.BackgroundWorker - другое решение, как SynchronizationContext.
Однако все они работают, отправляя известные сообщения Windows в цикл сообщений пользовательского интерфейса.Если вы вызываете Invoke слишком часто, вы отправляете слишком много сообщений, и поток пользовательского интерфейса забивается, что делает пользовательский интерфейс «немного запаздывающим».
Если это происходит, вы должны снизить скорость отправки сообщений.Есть несколько способов сделать это:
1) Вызывать Invoke реже: это означает ожидание больших "кусков" изменений состояния в фоновом потоке, прежде чем он вызовет Invoke для обновления пользовательского интерфейса.
2) Используйте таймер пользовательского интерфейса: нет смысла пытаться обновить пользовательский интерфейс быстрее, чем может обнаружить человеческий глаз.Таймер пользовательского интерфейса также отправляет сообщения Windows в цикл сообщений пользовательского интерфейса, но с известной скоростью.Затем обработчик Tick может извлечь необходимые данные из общей памяти для обновления пользовательского интерфейса.
Оба подхода имеют свои сильные и слабые стороны.Выбор действительно зависит от того, насколько просто сгруппировать изменения состояния в фоновом потоке в более крупные куски, при этом убедившись, что пользовательский интерфейс не пропустит никаких изменений состояния.