tags:

views:

47

answers:

2

I desperately need synchronous / blocking Animations in C# / WPF (executing code in the completed event is unfortunately not enough in my case).

I tried two ways:

1) Start the (asynchronous) animation using BeginAnimation with a Duration of x. Add Thread.Sleep(x) after the asynchronous call. However this doesn't work, the Animation is started AFTER the thread has slept for the given duration.

2) Using signals (AutoResetEvent class): Start the animation in another thread, the animations completed event signals that the animation was completed using a signal. Result: Code is never executed, whole thread is blocked, no animation shown / started, though the locked code starts after the BeginAnimation call. Maybe I'm using the signal in a wrong way? (I never used them before). (Idea based on this thread: http://stackoverflow.com/questions/632565/wpf-returning-a-method-after-an-animation-has-completed)

You can find a sample project at http://cid-0432ee4cfe9c26a0.office.live.com/self.aspx/%C3%96ffentlich/BlockingAnimation.zip

Thank you very much for any help!

BTW here's the plain code:

Method 1:

messageLogTB.Clear();

TranslateTransform translateTransform = new TranslateTransform();
animatedButton.RenderTransform = translateTransform;

DoubleAnimation animation = new DoubleAnimation(0, 200.0, new Duration(TimeSpan.FromMilliseconds(2000)));
translateTransform.BeginAnimation(TranslateTransform.XProperty, animation);

// Animation is asynchronous and takes 2 seconds, so lets wait two seconds here
// (doesn't work, animation is started AFTER the 2 seconds!)
Thread.Sleep(2000);
messageLogTB.Text += "animation complete";

Method 2:

messageLogTB.Clear();

TranslateTransform translateTransform = new TranslateTransform();
animatedButton.RenderTransform = translateTransform;

AutoResetEvent trigger = new AutoResetEvent(false);

// Create the animation, sets the signaled state in its animation completed event
DoubleAnimation animation = new DoubleAnimation(0, 200.0, new Duration(TimeSpan.FromMilliseconds(2000)));
animation.Completed += delegate(object source, EventArgs args) 
    {
        trigger.Set();
        messageLogTB.Text += "\nsignaled / animation complete";
    };


// Start the animation on the dispatcher
messageLogTB.Text += "starting animation";

Dispatcher.Invoke(
new Action(
    delegate()
    {
        translateTransform.BeginAnimation(TranslateTransform.XProperty, animation);
    }
), null);

// Wait for the animation to complete (actually it hangs before even starting the animation...)
trigger.WaitOne();
messageLogTB.Text += "\nThis should be reached after the signal / animation";
+1  A: 

Stop making it complex with threading. Use Animation's Completed event instead to chain multiple animations in a single sequence or execute some code in Completed event.

decyclone
A: 

You might want to post the context of what you are trying to accomplish because what you are describing is impossible in WPF. The animations run on the UI thread, and if you block UI thread, the animation does not happen.

Jeremiah Morrill