4

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.

Dusan
  • 5,000
  • 6
  • 41
  • 58
  • Did you also read the Remarks section in [Dispatcher.PushFrame](https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.pushframe(v=vs.110).aspx)? It explains it all, I guess. – Clemens Oct 07 '15 at 21:55
  • Yes, I have read that but it is still unclear. Does Dispatcher loop both initial Frame (created on startup) and my Frame one after another, or only my Frame? – Dusan Oct 07 '15 at 22:00
  • Also, what happens when I `PushFrame` and later on when I set `Contionue` to `false` – Dusan Oct 07 '15 at 22:01
  • 2
    PushFrame "enters an execute loop" (MSDN). 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. – Clemens Oct 07 '15 at 22:14
  • Great, that was one of my assumptions, also checked that in disassembled code and seems like that. Now, I am perfectly clear on what is going on. Please write the previous comment as an answer and I will accept it. Thanks a lot! – Dusan Oct 07 '15 at 22:22
  • http://stackoverflow.com/a/5183623/17034 – Hans Passant Oct 08 '15 at 06:53

2 Answers2

6

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.

Community
  • 1
  • 1
Clemens
  • 123,504
  • 12
  • 155
  • 268
0

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";
}
Serg046
  • 1,043
  • 1
  • 13
  • 42