Synchronous animations

by gleblanc 3. December 2008 12:39

In Silverlight, animations are launched asynchronously. Great... But sometimes, this feature makes things more complicated than necessary, as experienced in the following program that graphically renders the behavior of a sort algorithm. So, let's explain how to simulate synchronous animations. Doing so, we can keep the algorithm as it is. We just have a few lines to add, to launch animations.


Project / source code

Our sort algorithm is the simplest one. We know it's not efficient but we don't care since our goal is just to present synchronous animations. This algorithm (to sort the array T of integers) is :
 private void Sort()
 {
  for (int i = 0; i < T.Length-1; i++)
  {
   int mini= i+1;
   for (int j = i + 2; j < T.Length; j++)
    if (T[j] < T[mini]) mini = j;
   if (T[i] > T[mini])
   {
    // exchange
    int c = T[i]; T[i] = T[mini]; T[mini] = c;
   }
  }
 } 

If we run the Sort function as it is and we add animations, the program will end in less than a millisecond. Nothing will be visible : since animations can only be run asynchronously, a lot of animations would be launched asynchronously, within that millisecond ! Adding Thread.Sleep instructions would slowdown the program but would also stop animations. In technical terms : we cannot run Sort from the main (also named UI) thread. We could create a thread (ie another path of code execution) and execute Sort on this thread but actions on UI elements (changing colors or animations for instance) must be run from the main thread.

So, let's explain how to solve this dilemma. We first create a thread (in the function that handles the Click event on the Sort button) and launch Sort on that secondary thread :
 using System.Threading;        
 .....
 Thread thread;
 .....
 private void bSort_Click(object sender, RoutedEventArgs e)
 {
  .....
  thread = new Thread(new ThreadStart(Sort));
  thread.Start();
 }

Now, in the Sort function, we need to add instructions to change colors of bars and launch animations. To do so, we write the Display function, that will also run on the secondary thread. Display accepts as arguments a string (that contains the operation),  two integers (to eventually specify concerned UI elements) and a boolean indicating a pause is needed :
 int[] T;
 .....
 private void Sort()
 {
  .....
  for (int i = 0; i < T.Length-1; i++)
  {
   Display("Candidate", i, 0, true);
   .....
   int mini= i+1;
   ..... 
   for (int j = i + 2; j < T.Length; j++)
   {
    Display("Comparing " + T[i] + " with " + T[j] , 0, 0, true);
    ......
    if (T[j] < T[mini])
    {
     .....
    }
   }
   if (T[i] > T[mini])
   {
    Display("Move1", i, mini, false);
    Display("Move2", mini, i, true);
    .....
  }
 }
 .....
 void Display(string s, int a, int b, bool bDelay)
 {
  .....
  if (bDelay) Thread.Sleep(DELAY);
 }
Sure, the Sort function has been modified but we just added lines. Some algorithms are so complicated that it's better not go further.

Accesses to UI elements are performed in the Display function. How ? First, we need to add a delegate. A delegate is nothing new for C programmers : it's a function pointer (in other words, a variable that holds the address of a function, enabling the function call thru that pointer). Here, our delegate "points to" a function with three arguments (a string and two integers) :
 private delegate void LaunchAnimationDelegate(string s, int a, int b);
 .....
 LaunchAnimationDelegate LaunchAnimDel;
 .....
 private void Sort()
 {
  LaunchAnimDel = new LaunchAnimationDelegate(LaunchAnimation);
  .....
 }
 void Display(string s, int a, int b, bool bDelay)
 {
  Dispatcher.BeginInvoke(LaunchAnimDel, new object[] { s, a, b });
  .....
 }
 .....
 private void LaunchAnimation(string s, int a, int b)
 {
  .....
 }

We first defined a type (LaunchAnimationDelegate), ie an information for the compiler. Then a variable (named LaunchAnimDel) of that type. That variable is initialized at the beginning of the Sort function. Finally, we write the function (named LaunchAnimation) to be called thru that delegate. That function will be executed on the main, UI, thread. To force execution on the main thread, the function call must be performed with Dispatcher.BeginInvoke. See also how parameters are passed to the function. In LaunchAnimation, we can have any instruction that modifies UI elements, for instance
 tabRect[a].Fill = new SolidColorBrush(Colors.Orange);

Concerning the visual interface, let's say we have a Grid split into four lines. The second line (with the animation) is a Canvas that contains 10 Rectangle (height and color are changing but not position). We created two other rectangles for the Move animations, with storyboards created dynamically (at Loaded time). To keep code as easy as possible but have the bars growing from bottom to top, a ScaleTransform (with Y equals to -1) is performed on the Canvas. Source code is available, as usual.

Tags:

Comments

12/5/2008 12:41:49 PM #

Trackback from Community Blogs

Silverlight Cream for December 04, 2008 -- #445

Community Blogs

3/12/2009 12:00:56 AM #

This is great!  I'm always looking for ways to spruce up my programming.

Jacksonville Criminal Attorney United States

7/24/2009 9:26:59 PM #

Please let me know if you are interested to work as article writer for me? I can offer $10/article.

Tommy Bahama United States

8/11/2009 3:41:20 AM #

In searching for sites related to web hosting and specifically comparison hosting linux plan web, your site came up. Smile

cash loans United States

8/11/2009 3:41:23 AM #

:O So mush Info :O � THis Is he MOst AMAzing SIte DUDe� Laughing

cash loans United States

9/24/2009 3:07:03 AM #

As a Newbie, I am always searching online for articles that can help me. Thank you

payday loan United States

9/24/2009 3:07:09 AM #

Good post but not cool enough to rule. I usually never comment on posts, and yet I can't help leaving a comment: people never learn, they will always spam you! Amazing work.. beautiful �

payday loan United States

9/25/2009 12:24:47 AM #

Trackback from 4insure

Silverlight Cream for December 04, 2008 -- #445

auto insurance quotes United States

9/30/2009 7:29:24 AM #

This is an incredible code sample. I need to look into using Silverlight on my next project.

Temporary health insurance United States

9/30/2009 11:32:56 AM #

This is great!  I'm always looking for ways to spruce up my programming.

Tiffany Rings People's Republic of China

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

About the author

Gerard Leblanc is the author of several books (in french) on C++, C#, .NET and Silverlight (Eyrolles, Paris as publisher). See www.gleblanc.eu as the companion web site for these books (included sample programs).
He is Microsoft MVP for Silverlight.

MVP logo