参考我目前正在制作的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为机器人设置动画(使用BeginAnimation
或DispatcherTimer
)。
现在,问题是我没有在完成当前方法之前返回(即,转到下一个方法)的方法,因为这将导致动画一起发生,并且在无限循环中(就像上面的那个),这尤其不好。
我的问题是,在完成动画之前阻止方法返回的最佳方法是什么?
我目前在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
}
这样,方法在动画结束前不会返回。
但我觉得这不是正确的做法。
任何人都可以指导我做到最好吗?
答案 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甚至可能有一个针对此问题的固定解决方案,可以使用一行或两行代码。