Why is Frame Rate in WPF Irregular and Not Limited To Monitor Refresh?

后端 未结 3 1941
别跟我提以往
别跟我提以往 2020-12-02 23:48

I\'m measuring the time between frames in a simple WPF animation. Perforator says the app performs at ~60fps, so I expected the time between frames to be ~16.6ms with little

相关标签:
3条回答
  • 2020-12-03 00:04

    First - 'Christopher Bennage's-Answer has a good explanation and provides a hint to a solution:

    "Only do “per-frame” work when the reported frame time changes"

    This is a little bit hard, since the RenderingEventArgs are hidden as a normal EventArgs and a cast has to be done.

    To make this a little bit easyer, a convinient solution can be found in "EVAN'S CODE CLUNKERS" http://evanl.wordpress.com/2009/12/06/efficient-optimal-per-frame-eventing-in-wpf/

    I took his code and modified it a bit. Now just take my snipped, add the class to your Project, use CompositionTargetEx were you used CompositionTarget and you are fine :)

    public static class CompositionTargetEx { 
        private static TimeSpan _last = TimeSpan.Zero; 
        private static event EventHandler<RenderingEventArgs> _FrameUpdating; 
        public static event EventHandler<RenderingEventArgs> Rendering { 
            add { 
                if (_FrameUpdating == null)                 
                    CompositionTarget.Rendering += CompositionTarget_Rendering;
                _FrameUpdating += value; 
            } 
            remove { 
                _FrameUpdating -= value; 
                if (_FrameUpdating == null)                
                    CompositionTarget.Rendering -= CompositionTarget_Rendering; 
            } 
        } 
        static void CompositionTarget_Rendering(object sender, EventArgs e) { 
            RenderingEventArgs args = (RenderingEventArgs)e;
            if (args.RenderingTime == _last) 
                return;
            _last = args.RenderingTime; _FrameUpdating(sender, args); 
        } 
    }
    
    0 讨论(0)
  • 2020-12-03 00:12

    I raised this question with the WPF team and here is a summary of the response I was given:

    Calculating the framerate from the UI thread is difficult. WPF decouples the UI thread from the render thread. The UI thread will render:

    • Whenever something is marked as dirty and we drain down to Render priority. This can happen more often than the refresh rate.

    • If an animation is pending (or if someone hooked the CompositionTarget.Rendering event) we will render on the UI thread after every present from the render thread. This involves advancing the timing tree so animations calculate their new values.

    Because of this, the CompositionTarget.Rendering event can be raised multiple times per “frame”. We report the intended “frame time” in the RenderingEventArgs, and applications should only do “per-frame” work when the reported frame time changes.

    Note that the UI thread is doing many things, so it is not reliable to assume the CompositionTarget.Rendering event handler runs at a reliable cadence. The model we use (decoupling the two threads) means that the UI thread can be a little behind, since it is calculating animations for a future frame time.

    Special thanks to Dwayne Need for explaining this to me.

    0 讨论(0)
  • 2020-12-03 00:16

    WPF is not designed to be a constant frame rate rendering system. WPF renders to screen when the elements in the screen are marked as changed. The rendering system runs as a message loop so there is no way to ensure that a frame will be rendered at specific intervals.

    0 讨论(0)
提交回复
热议问题