0

I have a dilemma with my program. My program is like a specialized calculator, probability, dice roller type thing - think automated RPG rolling. And the way it's set up at the moment it on one window it has all the data and does all the calculations and such, BUT I also have a second, optional window that's purely for animations, just so it's not just text output. Now the animation window works fine, and as does my "data window" for lack of a better term, the issue becomes when I want to update my animation window from my data window and make the data window wait until the animation has completed.

Here's the set-up: Data window runs a method, within that method it tells animation window to update the images and run a storyboard animation method. That works. Now data window runs a method that has a foreach loop, and in that foreach loop it tells the animation window to update their image and run a animation for the current foreach item. Simple right? Well the problem is the data window is impatient and continues to tell the animation window to run it's animations - and since the animation is supposed to recycle a image object, just with a new source, with that animation, the animation window forgets all the orders from the data window and only runs the last one, rather than run each one one-by-one.

So basically my question is - how can I get my data window to wait for the animation window to finish their storyboard animation before continuing the foreach loop?

A simplified version of my code is this -

//In my data window
foreach (var item in Weapons)
{
try
            {
                string weapons = "\\" + weapon.Name + ".png";
                AnimationWindow.img_Pojectile.Source = new BitmapImage(new Uri(Directory.GetCurrentDirectory() + "\\Images" + weapons));
            }
            catch
            {
                try
                {
                    string weapons = "\\" + weapon.Type + ".png";
                    AnimationWindow.img_Pojectile.Source = new BitmapImage(new Uri(Directory.GetCurrentDirectory() + "\\Images" + weapons));
                }
                catch
                {
                    AnimationWindow.img_Pojectile.Source = new BitmapImage(new Uri(Directory.GetCurrentDirectory() + "\\Images\\Default.png"));
                }
            }

    AnimationWindow.Fire(item.Name);
//More code stuff I have to repeat here, all the calculations and such...
}

//In my AnimationWindow
public void Fire(string name)
{
    img_Pojectile.Source = new BitmapImage(new Uri(Directory.GetCurrentDirectory() + "\\" + name + ".png"));
    Storyboard sb = new Storyboard();
    DoubleAnimation anim = new DoubleAnimation(0, 120, TimeSpan.FromSeconds(seconds));
    TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;

anim.AutoReverse = true;
anim.RepeatBehavior = RepeatBehavior.Forever;
anim.BeginTime = TimeSpan.FromSeconds(offset);

Storyboard.SetTarget(anim, target);
Storyboard.SetTargetProperty(anim, new PropertyPath("(FrameworkElement.RenderTransform).(TranslateTransform.Y)"));

sb.Completed += (o, s) => {
//Figured a completed event might help, so far no luck
};

sb.Children.Add(anim);
sb.Begin();
}

So in this simpler version, what I'd like is for the animation finishes before my foreach loop moves on.

1 Answers1

0

I would suggest using a BackgroundWorker thread to execute the dice roll operation on a separate thread. When RunWorkerCompleted method is complete after your animation is done you can then carry on in your application.

e.g.

var bg = new BackgroundWorker();
            bg.DoWork += (s, e) =>
                             {
                                 // Do Dice roll animation
                                 // Disable data window 

                             };

            bg.RunWorkerCompleted += (s, e) =>
                            {
                               // Rice roll complete do other stuff
                               // Enable the data window
                            };

            bg.RunWorkerAsync();

Also check out the MSDN BackgroundWorker Class example.

kevchadders
  • 8,335
  • 4
  • 42
  • 61
  • I tried this but now I get the error "The calling thread cannot access this object because a different thread owns it." when I try to change the source of my img_projectile. Not sure if this is because of the bg or not but do you know any way past this? – GiantDwarf Aug 07 '14 at 08:02
  • I also put this inside the foreach loop, which may be the problem, and if so, then I don't think this'll work for me. I need to run the animation once per loop do more calculations after and stuff after within the same loop. – GiantDwarf Aug 07 '14 at 08:09
  • You may need to look into the System.Threading.Timer or DispatcherTimer. There are many SO links on this e.g. http://stackoverflow.com/questions/14354561/how-to-make-dispatchertimer-events-smoother-in-wpf – kevchadders Aug 07 '14 at 08:21
  • Either way I think you need some sort of threading so that on thread can be paused (data) while the other completes (animation) – kevchadders Aug 07 '14 at 08:22
  • How would I use it though? It seems to me a timer wouldn't work unless I could pause one thread from the other - which is precisely the question I'm asking. – GiantDwarf Aug 07 '14 at 08:37