Ваш пользовательский интерфейс не обновляется, потому что вся работа происходит в потоке пользовательского интерфейса.
Ваш звонок:
this.BeginInvoke((MethodInvoker)delegate() {update.Action.Run(); })
говорит invoke update.Action.Run () в потоке, который создал «this» (вашу форму), которая является потоком пользовательского интерфейса.
Application.DoEvents()
действительно даст потоку пользовательского интерфейса возможность перерисовать экран, но у меня будет соблазн создать новый делегат и вызвать для этого BeginInvoke.
Это выполнит функцию update.Action.Run () в отдельном потоке, выделенном из пула потоков. Затем вы можете продолжать проверять IAsyncResult до тех пор, пока обновление не будет завершено, запрашивая объект обновления на предмет его прогресса после каждой проверки (потому что другой поток не может обновить индикатор выполнения / пользовательский интерфейс), затем вызывая Application.DoEvents ().
Вы также должны впоследствии вызывать EndInvoke (), в противном случае вы можете потерять ресурсы
Я также хотел бы вставить кнопку отмены в диалоговое окно прогресса и добавить тайм-аут, в противном случае, если обновление застрянет (или займет слишком много времени), ваше приложение будет заблокировано навсегда.