WPF:动画完成后返回方法

时间:2009-03-10 22:40:28

标签: wpf animation callback

参考我目前正在制作的this programming game

我有一个类库(dll)将有一个方法Run,它将由以下内容组成:

public class MyRobot : Robot 
{
    public void Run(} 
    {
        while (true) 
        {
           Ahead(200); //moves the bot 200pixels
           TurnLeft(90); //turns the bot by 90deg 
        }
    }
}

在这些方法(继承自Robot)中,系统将使用WPF为机器人设置动画(使用BeginAnimationDispatcherTimer)。

现在,问题是我没有在完成当前方法之前返回(即,转到下一个方法)的方法,因为这将导致动画一起发生,并且在无限循环中(就像上面的那个),这尤其不好。


我的问题是,在完成动画之前阻止方法返回的最佳方法是什么?

我目前在bool班级(Robot)中有一个isActionRunning,当某个操作开始运行时会被标记为true,然后更改为false在动画回调中(如果使用Completed,则使用BeginAnimation事件。)

在每个方法结束时(在调用BeginAnimation之后),我放置了以下循环:

while (isActionRunning) 
{
    Thread.Sleep(200); //so that the thread sleeps for 200ms and then checks again if the animation is still running 
}

这样,方法在动画结束前不会返回。

但我觉得这不是正确的做法。

任何人都可以指导我做到最好吗?

3 个答案:

答案 0 :(得分:5)

从锁中建立信号装置是疯狂的;只需使用框架中已存在的信号设备。

http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx

那就是:第一个线程说“嘿线程二,开始这个动画,当你完成时,我会在这个等待句柄上发出信号。”线程一等待等待句柄。线程2启动动画,并在其完成事件中,向waithandle发出信号。线程一然后又醒来并说“嘿线程二,开始另一个动画......”

答案 1 :(得分:3)

这是一个选项,只有在Robot.Run代码运行在与执行动画的UI线程不同的线程中时,它才有效。

在Robot.Ahead方法(例如)中,使用Dispatcher.Invoke(不是BeginInvoke)来调用启动动画的方法,而不是使用空块在机器人上添加锁(lock(this){})

在启动动画的方法中,在开始动画之前调用Monitor.Enter(机器人)

在动画完成处理程序中调用Monitor.Leave(机器人)

结果将是

time      robot thread          UI thread  
  |       ---------------       --------------  
  |       call Invoke    --->  
  |                             lock robot (Monitor.Enter)  
  |                             begin animation  
  |       Invoke returns <---   return  
  |       lock(this)            (animation running)  
  |       (wait for lock  
  |       to become available)  
  |  
  |                             Animation complete  
  |                             release lock (Monitor.Exit)  
  |       (lock available,  
  |       continue running)  
  |       Release lock (exit lock block)  
  |       Return and start next  
  |       movement  
  \/  

答案 2 :(得分:0)

我会做类似你所描述的事情。我最近在一些事情上工作,我调用了一堆异步操作,我想在调用另一个操作之前等待它们全部完成。我创建了一个集合来表示当前正在执行的所有操作,而不是直接向集合添加项目,我创建了添加和删除的方法。 remove方法的逻辑表示“锁定集合,删除提供的密钥,如果为空则调用下一个操作”。您可以创建一个类似于此的机制,其中作用域应用程序或窗口的集合跟踪正在执行的操作。您向集合添加密钥并将此密钥传递给异步操作。异步操作完成后,锁定集合并删除密钥。然后你可以有一个循环阻止你的方法返回,而集合包含密钥(使用可选的逻辑来添加超时或任何其他方法,你可能希望方法能够返回而不是永远被阻止)。 / p>

这可能有点矫枉过正,但我​​自己对此问题的经验有限。据我所知,.Net甚至可能有一个针对此问题的固定解决方案,可以使用一行或两行代码。