title: How do I block access to a method until animations are complete
body: <p>I have a Silverlight app. that has a basic animation where a rectangle is animated to a new position. The animation consists of two DoubleAnimation() - one transforms the X, the other transforms the Y. It works OK. </p>
  
  <p>I basically want to block any other calls to this animate method until the first two animations have completed. I see that the DoubleAnimation() class has a Completed event it fires but I haven't been successful in constructing any kind of code that successfully blocks until both have completed.</p>
  
  <p>I attempted to use Monitor.Enter on a private member when entering the method, then releasing the lock from one of the animations Completed event, but my attempts at chaining the two events (so the lock isn't released until both have completed) haven't been successful.</p>
  
  <p>Here's what the animation method looks like:</p>
  
  <pre><code>    public void AnimateRectangle(Rectangle rect, double newX, double newY)
      {
              var xIsComplete = false;
  
              Duration duration = new Duration(new TimeSpan(0, 0, 0, 1, 350));
              var easing = new ElasticEase() { EasingMode = EasingMode.EaseOut, Oscillations = 1, Springiness = 4 };
              var animateX = new DoubleAnimation();
              var animateY = new DoubleAnimation();
  
              animateX.EasingFunction = easing;
              animateX.Duration = duration;
              animateY.EasingFunction = easing;
              animateY.Duration = duration;
  
              var sb = new Storyboard();
  
              sb.Duration = duration;
              sb.Children.Add(animateX);
              sb.Children.Add(animateY);
  
              Storyboard.SetTarget(animateX, rect);
              Storyboard.SetTargetProperty(animateX, new PropertyPath("(Canvas.Left)"));
              Storyboard.SetTarget(animateY, rect);
              Storyboard.SetTargetProperty(animateY, new PropertyPath("(Canvas.Top)"));
  
              animateX.To = newX;
              animateY.To = newY;
              sb.Begin();
  
      }
  </code></pre>
  
  <p>EDIT (added more info)</p>
  
  <p>I ran into this initially because I was calling this method from another method (as it processed items it made a call to the animation). I noticed that the items didn't end up where I expected them to. The new X/Y coordinates I pass in are based on the items current location, so if it was called multiple times before it finished, it ended up in the wrong location. As a test I added a button that only ran the animation once. It worked. However, if I click on the button a bunch of times in a row I see the same behavior as before: items end up in the wrong location.</p>
  
  <p>Yes, it appears Silverlight animations are run on the main UI thread. One of the tests I tried I added two properties that flagged whether both animations had completed yet. In the AnimateRectange() method I checked them inside of a while loop (calling Thread.Sleep). This loop never completed (so it's definitely on the same thread). </p>
  
  <p>So I created a queue to process the animations in order:</p>
  
  <pre><code>    private void ProcessAnimationQueue()
      {
          var items = this.m_animationQueue.GetEnumerator();
          while (items.MoveNext())
          {
              while (this.m_isXanimationInProgress || this.m_isYanimationInProgress)
              {
                  System.Threading.Thread.Sleep(100);
              }
  
              var item = items.Current;
              Dispatcher.BeginInvoke(() =&gt; this.AnimateRectangle(item.Rect.Rect, item.X, item.Y));                
          }
      }
  </code></pre>
  
  <p>Then I call my initial routine (which queues up the animations) and call this method on a new thread. I see the same results.</p>