c# progressbar не обновляется
У меня есть ProgressBarWindow, который имеет progressbar и кнопку отмены на нем, который я использую для отчета о прогрессе в файле ввода-вывода. однако поток пользовательского интерфейса ProgressBarWindow и мое главное окно оба висят, несмотря на всю работу, выполняемую в backgroundworker. Progressbar отображается, как и мое главное окно, но не обновляется, пока backgroundworker делает свое дело. Следующий код вызывается в самом конце конструктора, главного окно:
iCountLogLinesProgressBar = new ProgressBarWindow();
iCountLogLinesProgressBar.cancelButton.Click += EventCountLogLinesProgressBarCancelButtonClicked;
iCountLogLinesProgressBar.Show();
iCountLogRecords = new BackgroundWorker();
iCountLogRecords.DoWork += EventCountLogLinesDoWork;
iCountLogRecords.ProgressChanged += EventCountLogLinesProgressChanged;
iCountLogRecords.RunWorkerCompleted += EventCountLogLinesRunWorkerCompleted;
iCountLogRecords.WorkerReportsProgress = true;
iCountLogRecords.WorkerSupportsCancellation = true;
iCountLogRecords.RunWorkerAsync(new BinaryReader(File.Open(iMainLogFilename, FileMode.Open, FileAccess.Read)));
EventCountLogLinesProgressChanged () выглядит следующим образом:
private void EventCountLogLinesProgressChanged(object sender, ProgressChangedEventArgs e)
{
iCountLogLinesProgressBar.Value = e.ProgressPercentage;
}
вот сокращенная версия ProgressBarWindow (остальное - всего лишь пара сеттеров):
public partial class ProgressBarWindow : Window
{
public ProgressBarWindow()
{
InitializeComponent();
this.progressBar.Value = this.progressBar.Minimum = 0;
this.progressBar.Maximum = 100;
}
public double Value
{
get
{
return progressBar.Value;
}
set
{
this.progressBar.Value = value;
}
}
}
Я попытался обернуть строку задатчика значений в диспетчер.вызовите делегат, но это дает мне переполнение стека (мне не нужен диспетчер.вызовите строку в любом случае, как backgroundworker вызывает ProgressChanged в потоке пользовательского интерфейса, верно?). Я проверил msdn и googled но я не могу найти никого с этой проблемой.
редактировать извинения, я не понял, что мой упрощенный код заблокировал поток пользовательского интерфейса, я получаю точно такое же поведение, несмотря на использование backgroundworker, поэтому я ошибочно предположил, что они эквивалентны. Я должен был упомянуть, что использую backgroundworker: P
2 ответов
вы блокируете поток пользовательского интерфейса, поэтому он не будет повторно отображать пользовательский интерфейс, пока ваш цикл не закончится.
переместите фоновую обработку в отдельный поток и используйте соответствующий Dispatcher
вызовов (или BackgroundWorker
) для маршалирования UI update вызывает обратно в поток UI.
Если ваш индикатор прогресса действительно просто хотел быть таймером, вы можете использовать один из Timer
классы для его обновления.
EDIT: хорошо, теперь вы изменили код, он выглядит нормально для меня. Он должен быть потокобезопасным, поскольку вы только меняете пользовательский интерфейс в потоке пользовательского интерфейса. Ваш фоновый работник определенно периодически сообщает о прогрессе?
слушайте Джона Скита, или вы можете иногда позвонить в приложение.DoEvents (), чтобы сделать все обновления пользовательского интерфейса в одном потоке.