Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF DispatcherFrame magic - how and why this works?

Tags:

c#

wpf

I was trying to animate some stuff in WPF and run some other operations when animation finishes.

Also, wanted to avoid animation finish callback mechanism, so, I came up with a solution illustrated in the code below:

// Start one second of animation
...

// Pause for one second
Wait(this.Dispatcher, 1000);

// Continue and do some other stuff
...

Now, the interesting part is Wait method which magically makes blocking pause in my code but the animation and UI stays normal, responsive:

    public static void Wait(Dispatcher Dispatcher, int Milliseconds)
    {
        var Frame = new DispatcherFrame();
        ThreadPool.QueueUserWorkItem(State =>
        {
            Thread.Sleep(Milliseconds);
            Frame.Continue = false;
        });
        Dispatcher.PushFrame(Frame);
    }

I have read a documentation and a few articles about DispatcherFrame but I am still unable to figure out what is really happening under the hood, and I need some clarification about how this construction with PushFrame really works.

like image 773
Dusan Avatar asked Oct 22 '25 15:10

Dusan


2 Answers

From MSDN:

PushFrame

Enters an execute loop.

That loop (i.e. the DispatcherFrame) executes as long as its Continue property is true.

As soon as the Continue property goes to false, the loop/frame is exited and the Dispatcher returns to the loop/frame that it executed before you called PushFrame.

like image 101
Clemens Avatar answered Oct 24 '25 03:10

Clemens


If you want take a pause, why not anything like this?

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    var btn = sender as Button;
    btn.Content = "Before pause";

    var animation = new DoubleAnimation();
    animation.From = btn.ActualWidth;
    animation.To = 100;
    animation.Duration = TimeSpan.FromSeconds(2);

    btn.BeginAnimation(Button.WidthProperty, animation);

    await Task.Delay(2000);

    btn.Content = "After pause";
}
like image 38
Serg046 Avatar answered Oct 24 '25 04:10

Serg046