Анимация непрозрачности формы в C # с помощью BackgroundWorker - PullRequest
1 голос
/ 19 мая 2009

С помощью BackgroundWorker я создал анимацию непрозрачности для некоторой формы.

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

«Медленная анимация», о которой я говорю, не заикается, анимация на самом деле очень плавная, просто требуется больше времени для выполнения всей анимации (от 0% до 100% или наоборот). Это происходит только время от времени. Кажется (не уверен), что это происходит, когда компьютер выполняет какое-то другое, несколько интенсивное фоновое действие.

Конечно, мне нужно это исправить, но я также хотел бы знать, если вы все равно улучшите этот код или сделаете это по-другому и / или лучше.

Вот мой код:

private const int TOGGLE_EFFECT_SPEED = 10;

private void blendWorker_DoWork(object sender, DoWorkEventArgs e) {
    bool blendIn = (bool)e.Argument;

    // Loop through all opacity values
    for(double value = 1; value <= 100; value += 1) {
        // Report the current progress on the worker
        blendWorker.ReportProgress(0, blendIn ? value : 100 - value);

        // Suspends the current thread by the specified blend speed
        System.Threading.Thread.Sleep(11 - TOGGLE_EFFECT_SPEED);
    }

    // Set the worker result as the inverse tag value
    e.Result = !blendIn;
}

private void blendWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
    double opValue = (double)e.UserState;

    // Show and repaint the whole main notes window?
    if(opValue == 1.0) {
        Show();
        Invalidate(true);
    }

    // Set the main notes window opacity value
    Opacity = (double)e.UserState / 100;
}

private void blendWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
    bool tagFlag = (bool)e.Result;

    // Hide the main notes window?
    if(tagFlag) {
        Hide();
    }

    // Set the main notes window tag value
    Tag = tagFlag;
}

/*
   THE FOLLOWING METHOD IS PART OF A DIFFERENT CLASS.
   ACTUALLY, IT'S THE "PROGRAM" CLASS WHERE MAIN()
   IS LOCATED. THIS METHOD IS CALLED TO SHOW/HIDE
   THE MAIN APPLICATION FORM WITH AN OPACITY ANIMATION
*/
internal static void ToggleNotesWindow() {
    // Get the tag value converted to boolean type
    bool tagFlag = Convert.ToBoolean(NotesWindow.Tag, CultureInfo.InvariantCulture);

    // Bring the main notes window to front?
    if(tagFlag) Program.NotesWindow.BringToFront();

    // Run the blend effect if it's not already running
    if(!NotesWindow.blendWorker.IsBusy) {
        NotesWindow.blendWorker.RunWorkerAsync(tagFlag);
    }

    // Activate and focus the main notes window?
    if(tagFlag) Program.NotesWindow.Activate();
}

Ответы [ 2 ]

1 голос
/ 19 мая 2009

Каждый раз, когда вы изменяете непрозрачность формы, Windows должна перерисовывать все окна под ним, само окно, а затем применять непрозрачность (Vista делает это намного быстрее и буферизуется). Поскольку вы проходите через каждое состояние непрозрачности от 1 до 100, этот процесс должен завершиться 100 раз. Иногда перерисовка вашего окна или окна под ним будет медленной.

Метод Thread.Sleep со значением> 0 будет спать от 0 ... ~ 10 мс независимо от того, какое значение вы передаете. Разрешение таймера планировщика потоков в Windows составляет около 10 мс (опять же, Vista и другие ОС меняются и оптимизируются, так что это не точно), поэтому вы не можете запланировать временной интервал меньше этого. 100x10ms + время фактического рендеринга может занять 2 целых секунды, чтобы исчезнуть.

Способ ускорить его - уменьшить количество повторных розыгрышей. Вместо шага +1 для непрозрачности, шага +5, +10 и т. Д. Это уменьшает общее количество необходимых повторных прорисовок и приводит к потере формы за 100 мс.

0 голосов
/ 19 мая 2009

В целом, я не вижу ничего, что могло бы оправдать изменения, по крайней мере, на первый взгляд. Если вы видите некоторые узкие места в производительности, вы можете попробовать взглянуть на Ants Profiler или аналогичный инструмент для профилирования кода, чтобы определить, можно ли определить какие-либо медленные участки.

...