C # - BackgroundWorker Постоянно обновляемый элемент управления: Ошибка! - PullRequest
2 голосов
/ 18 ноября 2010

По какой-то причине у меня традиционно много проблем с BackgroundWorkers в C #;кажется, что их концепция действительно вводит меня в заблуждение, поэтому я надеюсь, что это довольно простой вопрос, и кое-что может быть исправлено достаточно легко ...

У меня есть две формы, использующие удаленное взаимодействие .NET для связи между ними,Прямо сейчас, изменение настроек в Form1 вызывает изменения в Form2, и это прекрасно работает.Однако теперь мне нужно, чтобы та же самая вещь работала другим способом (изменение чего-либо в Form2 приводит к обновлению Form1), и я не могу сделать это таким же образом (из-за ограничений в дизайне я не могу заставить Form2 отправить изменениедо формы 1).Прямо сейчас я пытаюсь использовать BackgroundWorker в Form1, чтобы постоянно вызывать метод «Update ()» для каждого из подчиненных элементов управления (которые размещены в Form1).У каждого из этих элементов управления есть возможность получить текущее состояние их эквивалентных настроек из Form2 и обновить себя (это работает хорошо; метод Update () уже работает над инициализацией Form1).

Вот тут и возникает моя проблема.Я не был уверен, как заставить BackgroundWorker постоянно вызывать Update () для каждой из форм, поэтому в моем методе DoWork () у меня есть цикл while (true), и внутри него BackgroundWorker вызывает Update() 'метод каждого субконтроля, затем спит в течение очень короткого времени, а затем повторяется.

При этом я получаю ошибку «InvalidOperationException не обрабатывается кодом пользователя» с деталями, указывающими, что «Кросс-нитьнедопустимая операция: элемент управления 'comboBox_BGColor' доступен из потока, отличного от потока, в котором он был создан. "Теперь я в основном знаю, что это значит, и понимаю, почему это произошло, однако я не уверен, что нужно делать по-другому или как изменить вещи, чтобы они работали по своему усмотрению.У кого-нибудь есть какие-либо советы по этому поводу или как я использую BackgroundWorker?Большое спасибо за любую информацию и за то, что нашли время прочитать это!

Ответы [ 3 ]

3 голосов
/ 18 ноября 2010

Элементы управления пользовательского интерфейса имеют сходство потоков .Не следует прикасаться к элементам управления (для чтения или записи) из любого потока, кроме потока пользовательского интерфейса.Если BackgroundWorker говорит в основном с пользовательским интерфейсом, вам, вероятно, будет лучше, если вы просто используете элемент управления Timer, избегая необходимости многократно вызывать Invoke или BeginInvoke.

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

1 голос
/ 18 ноября 2010

Исключение, которое вы получите, будет результатом вызова Update() (который изменяет одну или несколько форм в вашем основном потоке) напрямую из _DoWork в потоке BackgroundWorker.

Если вы 'Вы собираетесь использовать метод BackgroundWorker:

  • Установите свойство .WorkerReportsProgress вашего работника на true
  • Когда вы выполняете цикл, используйте.ReportProgress() метод работника для запуска обработчика события _ProgressChanged работника.
  • Обработчик события _ProgressChanged может затем безопасно выполнить вызов метода Update() вашей формы

Если вы откажетесь от использования работника (особенно если ваш фоновый работник существует исключительно для этого цикла), то я бы предложил вам воспользоваться предложением Марка стандартных обработчиков событий.Этот маршрут приведет к меньшим нагрузкам на процессор (как минимум на данный момент, а может и не быть), чем добавление в ваш внешний цикл или элемент управления Timer.

Любой маршрут должен учитывать исключение Cross-thread.

1 голос
/ 18 ноября 2010

вам нужен таймер вместо фонового рабочего

...