C #, обновление индикатора выполнения с использованием фонового рабочего из другого класса

#c# #backgroundworker

#c# #BackgroundWorker

Вопрос:

Я пытаюсь обновить индикатор выполнения в основной форме, поскольку работа выполняется в другом классе. Например:

 private void transfer_Click(object sender, EventArgs e)
{
    Guid aspnetUserId = Guid.Parse(System.Configuration.ConfigurationSettings.AppSettings["ASPNetUserID"]);
    WC1toWC2Transfer transfer = new WC1toWC2Transfer(aspnetUserId);

    backgroundWorker1.RunWorkerAsync(transfer);  
}
 

И затем в фоновом методе фактически вызывается метод:

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    WC1toWC2Transfer transfer = e.Argument as WC1toWC2Transfer;
    transfer.WC1ToWC2EmployerTransfer(log, wc1ConnStr, wc2ConnStr, progressBar1);
}
 

В методе WC1ToWC2EmployerTransfer я устанавливаю максимум индикатора выполнения и обновляю значение каждый раз, когда что-то передается в базу данных в этом методе, но когда я делаю это, ничего не происходит. Внутри метода есть код, который запускает хранимую процедуру в базе данных, но как только он попадает в эту часть кода, он прекращает отладку, и мне приходится запускать процесс снова.

Я делаю здесь что-то не так? Нужно ли мне переписывать то, что у меня есть, чтобы фактические методы были в основной форме, а не в другом классе? Я младший разработчик (начал работать всего несколько месяцев назад), поэтому простите меня, если я делаю что-то явно неправильное или недостаточно хорошо объяснил это.

Любая помощь будет с благодарностью принята.

Комментарии:

1. Не уверен, о чем это, но вы определенно захотите устранить неполадки «это останавливает отладку». BackgroundWorker проглатывает исключения и передает их обработчику событий RunWorkerCompleted со свойством e.Error . Что-то, что вы не хотите игнорировать. Лучший способ не игнорировать это с помощью Debug Exceptions, установите флажок для исключений CLR.

Ответ №1:

Вы не можете изменить пользовательский интерфейс, если вы не находитесь в основном потоке, которым вы, фоновый рабочий, не будете.

Что вам нужно сделать, это создать обработчик событий в основной форме для обработки события ProgressChanged backgroundworker.

например

 // this method should be in your main form.
private void backgroundworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // update your progress bar here.
}
 

В вашем фоновом рабочем вы вызываете метод ReportProgress, который запускает событие ProgressChanged.


Здесь есть хороший пример.

Ответ №2:

Я думаю, причина в том, что вы получаете an IllegalCrossThreadException , потому что вы пытаетесь получить доступ к элементу управления из другого потока, чем он был создан. BackgroundWorker Предоставляет метод ReportProgress и событие ProgressChanged, которое обычно используется для такого обновления и которое будет выполняться в потоке пользовательского интерфейса. При доступе к progressbar из другого потока, отличного от потока пользовательского интерфейса, сделайте это следующим образом:

 if(progressBar1.InvokeRequired) {
  progressBar1.Invoke(new MethodInvoker(delegate { progressBar1.Maximum = someValue; }));
}
 

В качестве примечания: передача панели прогресса вашему рабочему классу — не очень хороший дизайн. Форма может закрыться, она может быть удалена, и рабочий ничего об этом не узнает, в конечном итоге произойдет сбой, ObjectDisposedException который, вероятно, не будет обнаружен. Кроме того, вы ставите работника в зависимость от System.Windows.Forms того, когда в этом, вероятно, нет необходимости. Вместо этого пусть ваш работник сообщает о ходе выполнения события и передает это на вашу панель выполнения из класса, который создал работника.

Комментарии:

1. Кроме того, если вам интересно, Progression (отказ от ответственности: я написал это) — это очень простая библиотека для вычисления прогресса, которая позволяет вашим рабочим методам корректно сообщать о прогрессе, ничего не зная об пользовательском интерфейсе. Либо пользовательский интерфейс подписывается на потокобезопасные события, либо BackgroundWorker может подписаться на события и сообщать о них.