Я имею, столкнулся с тем, что я считаю ошибкой индикатора выполнения в Windows 7. Для демонстрации ошибки, я создал приложение WinForm с кнопкой и индикатором выполнения. В кнопке 'по щелчку' обрабатывают, у меня есть следующий код.
private void buttonGo_Click(object sender, EventArgs e)
{
this.progressBar.Minimum = 0;
this.progressBar.Maximum = 100;
this.buttonGo.Text = "Busy";
this.buttonGo.Update();
for (int i = 0; i <= 100; ++i)
{
this.progressBar.Value = i;
this.Update();
System.Threading.Thread.Sleep(10);
}
this.buttonGo.Text = "Ready";
}
Ожидаемое поведение состоит в том, чтобы индикатор выполнения совершенствовался к 100% и затем текст кнопки для изменения на 'Готовый'. Однако при разработке этого кода Windows 7, я заметил, что индикатор выполнения повысится приблизительно до 75%, и затем текст кнопки изменился бы на 'Готовый'. Принятие кода синхронно, этого не должно происходить!
На дальнейшем тестировании я нашел, что тот же самый код, работающий на Windows Server 2003, привел к ожидаемым результатам. Кроме того, выбор non aero theme on Windows 7 produces the expected results.
В моем уме это походит на ошибку. Часто очень трудно сделать индикатор выполнения точным, когда долгая операция включает сложный код, но в моем особом случае это было очень прямым и таким образом, я был мало разочарован, когда я нашел, что управление прогрессом точно не представило прогресс.
Кто-либо еще заметил это поведение? Кто-либо нашел обходное решение?
Я видел похожие проблемы с индикаторами выполнения в Vista и Windows 7.
Ключевой проблемой в моем случае была блокировка потока пользовательского интерфейса. (Как и в вашем примере).
Windows не любит приложения, которые не отвечают на новые сообщения в очереди сообщений. Если вы потратите слишком много времени на одно сообщение, окна отметят ваше приложение как «не отвечающее». В Vista / Win7 Windows также решает прекратить обновление окна вашего приложения.
В качестве обходного пути вы можете поручить фактическую работу фоновому исполнителю или время от времени вызывать Application.DoEvents ()
. Вам нужно убедиться, что окно индикатора выполнения является модальным, иначе DoEvents () может разрешить запуск новых команд на полпути в фоновой обработке.
Если вам кажется, что это непонятно, более правильный способ - выполнить фоновую работу в потоке BackgroundWorker
. Он поддерживает отправку событий в поток пользовательского интерфейса для обновления индикатора выполнения.
Я думаю, что исходная проблема связана с синхронизацией и механизмом анимации Win7 (или Aero) для индикатора выполнения.
Эта подпрограмма находится в форме, содержащей индикатор выполнения (pBar).
Он изменяет .Maximum столбца и сохраняет .Value фиксированным на 10 для процентов завершения от 1 до 99. .Minimum столбца устанавливается на 0 во время разработки.
Это решило мою проблему.
Public Sub UpdateStatusPC(ByVal pc As Integer)
Try
If pc < 0 Then
pBar.Maximum = 100
pBar.Value = 0
ElseIf pc > 100 Then
pBar.Maximum = 100
pBar.Value = 100
ElseIf pc = 0 Then
pBar.Maximum = 10
pBar.Value = 0
Else
pBar.Value = 10
pBar.Maximum = 10 / CDbl(pc / 100.0)
End If
pBar.Update()
Catch ex As Exception
MsgBox("UpdateStatusPC: " & ex.Message)
End Try
End Sub
Это связано с анимацией индикатора выполнения. Если ваш индикатор выполнения находится на 0%, а вы установили его на 100%, он не будет там прыгать, а будет анимировать индикатор выполнения, плавно заполняющийся. Если это слишком медленно, вы закончите до того, как анимация индикатора выполнения завершится. Таким образом, даже если вы уже установили 80, 90 и 100%, анимация все равно отстает.
Я так и не нашел способа отключить это, но у меня есть обходной путь. Анимация выполняется только в том случае, если вы увеличиваете индикатор выполнения. Если вы переместите его назад, он немедленно перейдет в это положение. Поэтому, если я хочу, чтобы индикатор выполнения был на уровне x% (x! = 100), я перемещаю его на x + 1, а затем на x. Если мне нужно 100%, я перехожу на 100, 99 и 100%. (Или любые значения, которые вы используете, вы поняли.) Это работает достаточно быстро, чтобы не быть видимым, и вы можете оставить этот код и для предыдущих версий Windows (хотя я этого не делаю).
Отключите параметр визуального эффекта «Анимировать элементы управления и элементы внутри окон» в «Параметры производительности». Тогда индикаторы выполнения больше не будут анимированы.