Можно ли обновить пользовательский интерфейс из фонового рабочего события?

Я видел других с похожей проблемой, но не совсем то, что я искал. В событии dowork класса backgrounderworker я создаю экземпляр нового класса и вызываю одну из его функций. Раньше у меня был этот код в событии тика windows.form.timer, и я передал делегат в качестве одного из параметров, который позволил бы функции и другим функциям, которые она вызывает в классе, вызывать метод в форме для обновления сетки данных. на графическом интерфейсе. Есть ли способ сделать это в рамках события dowork? Мне это нужно, потому что функция, которую я вызываю из dowork, вызывает другие функции, и я хочу, чтобы каждая из этих функций регистрировала информацию в сетке данных графического интерфейса.


person daustin    schedule 22.09.2010    source источник


Ответы (3)


Для этого предназначен метод BackgroundWorker.ReportProgress(). Вы реализуете событие ProgressChanged для обновления пользовательского интерфейса, оно будет выполняться в основном потоке. Вы не ограничены сообщением только о проценте выполнения, вы также можете передать любой объект, чтобы передать информацию обработчику событий, используя перегрузку, которая принимает аргумент userState. Помните, что вам придется использовать правильную блокировку, если вы это сделаете.

person Hans Passant    schedule 22.09.2010
comment
Не забудьте установить для свойства WorkerReportsProgress значение true самого фонового рабочего. - person Scott Anderson; 23.09.2010
comment
Вот проблема, с которой я столкнулся при использовании ReportProgress. В DoWork я вызываю функцию. Эта функция вызывает другие функции. Я хочу, чтобы все эти функции могли отправлять обновления статуса в пользовательский интерфейс. - person daustin; 23.09.2010
comment
Итак, напишите функцию, которая вызывает ReportProgress, чтобы ее могли вызывать все остальные функции. Передайте делегата, если вам нужно. Будьте осторожны, маршалинг потоков стоит очень дорого. Вызовите его более ~ 1000 раз в секунду, и поток пользовательского интерфейса перестанет работать, когда он больше не сможет поддерживать работу. - person Hans Passant; 23.09.2010

Помимо ReportProgess, упомянутого в ответе Ганса, вы также можете использовать Control.Invoke на одном из элементов пользовательского интерфейса для выполнения кода в потоке пользовательского интерфейса.

person Heinzi    schedule 22.09.2010
comment
Но могу ли я в DoWork передать эту возможность (как параметр делегата) классу, который я создаю в DoWork? - person daustin; 23.09.2010
comment
@ user94593: Страница MSDN Control.Invoke (см. ссылку в моем ответе) содержит пример в конце. - person Heinzi; 28.09.2010
comment
@user94593: Вторая перегрузка, которая позволяет передавать параметры, также может быть вам интересна (опять же, пример приведен внизу): msdn.microsoft.com/en-us/library/a1hetckb.aspx - person Heinzi; 28.09.2010

Вы можете отправить данные о прогрессе обратно в поток пользовательского интерфейса, вы получите событие для этого в потоке пользовательского интерфейса, а затем сможете обновить экран. Настоятельно рекомендуется, чтобы объекты, которые вы отправляете обратно в поток пользовательского интерфейса, были неизменяемыми. Помимо вызова ReportProgress и обработки события, вам необходимо подписаться, установив для свойства WorkerSupportsProgress значение true.

person Community    schedule 22.09.2010