简体   繁体   English

使用BackgroundWorker在C#中形成表格不透明度动画

[英]Form opacity animation in C# with a BackgroundWorker

With the help of the BackgroundWorker, I created an opacity animation for some form. 在BackgroundWorker的帮助下,我为某种形式创建了不透明度动画。

There's only one tiny issue with this approach but I can't understand where is the problem. 这种方法只有一个小问题,但我不明白问题出在哪里。 The animation speed is configurable and even if the speed value is very high, sometimes the animations is very, very slow, for some odd reason... 动画速度是可配置的,即使速度值很高,有时出于某些奇怪的原因,动画也非常非常慢...

The "slow animation" I'm talking about it's not stutter, the animation is actually very smooth, it just takes more time to perform the whole animation (from 0% to 100%, or vice-verse). 我所说的“慢速动画”不是口吃,实际上动画非常流畅,执行整个动画只需要更多时间(从0%到100%,反之亦然)。 This only happens from time to time. 这只会不时发生。 It seems (not sure) that it happens when the computer is doing some other, somewhat intensive, background action. 似乎(不确定)在计算机执行其他一些强度较大的后台操作时发生。

I need to fix that of course but I also would like to know if there's anyway you would improve this code or if you would do it differently and/or better. 我当然需要修复该问题,但我也想知道是否无论如何您都会改进此代码,或者是否可以做不同的事情和/或做得更好。

Here's my code: 这是我的代码:

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

Each time you change the opacity of the form, Windows has to redraw all the windows below it, the window itself and then apply opacity (Vista does this much faster and buffered). 每次更改窗体的不透明度时,Windows都必须重新绘制其下方的所有窗口(窗口本身),然后应用不透明度(Vista可以更快地完成此操作并进行缓冲)。 Since you're stepping through each opacity state from 1...100 this process has to complete 100 times. 由于您要从1 ... 100开始逐步进入每个不透明度状态,因此此过程必须完成100次。 Sometimes redrawing your window or a window below it will be slow. 有时重新绘制窗口或它下面的窗口会很慢。

The Thread.Sleep method with a value > 0 will sleep from 0...~10ms no matter what value you pass. 值大于0的Thread.Sleep方法无论您传递什么值,都将从0 ...〜10ms休眠。 The thread scheduler timer resolution on Windows is approx 10ms (Again, Vista and other OS change and optimize so it's not exact) so you can't schedule a time slice smaller than that. Windows上的线程调度程序计时器分辨率约为10毫秒(再次,Vista和其他OS进行了更改和优化,因此不太准确),因此您不能调度比该时间段短的时间片。 100x10ms + the time to actually render might take 2 whole seconds to fade in/out. 100x10ms +实际渲染时间可能需要2整秒才能淡入/淡出。

The way to speed it up is to reduce the number of re-draws. 加快速度的方法是减少重画次数。 Rather than stepping +1 for opacity, step +5, +10, etc. That reduces the total number of re-draws required and would result in a form fading in 100ms instead. 而不是针对不透明度步进+1,而是步进+ 5,+ 10,等等。这样可以减少所需的重画总数,从而导致表单淡入100ms。

Overall I don't see much that would warrant a change at least at first glance. 总体而言,至少第一眼我认为没有什么值得改变的地方。 If you are seeing some performance bottlenecks you might try having a look at Ants Profiler or a similar code profiling tool to see if you can pinpoint any slow sections. 如果您发现一些性能瓶颈,则可以尝试查看Ants Profiler或类似的代码分析工具,以查看是否可以查明任何缓慢的部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM