1

在 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();
}
4

2 回答 2

1

每次更改窗体的不透明度时,Windows 都必须重新绘制它下面的所有窗口、窗口本身,然后应用不透明度(Vista 执行此操作要快得多并且有缓冲)。由于您从 1...100 逐步完成每个不透明度状态,因此此过程必须完成 100 次。有时重绘你的窗口或它下面的窗口会很慢。

无论您传递什么值,值 > 0 的 Thread.Sleep 方法都会从 0...~10ms 休眠。Windows 上的线程调度程序计时器分辨率约为 10 毫秒(同样,Vista 和其他操作系统会更改和优化,因此并不准确),因此您无法安排比这更小的时间片。100x10ms + 实际渲染的时间可能需要 2 整秒才能淡入/淡出。

加快它的方法是减少重画的次数。而不是为不透明度步进 +1,步进 +5、+10 等。这减少了所需的重新绘制的总数,并且会导致表单在 100 毫秒内褪色。

于 2009-05-19T19:22:29.320 回答
0

总的来说,至少乍一看,我看不出有太多值得改变的地方。如果您发现一些性能瓶颈,您可以尝试查看 Ants Profiler 或类似的代码分析工具,看看您是否可以查明任何慢速部分。

于 2009-05-19T18:26:18.797 回答