参考Software Project I am currently working on。
我有以下方法基本上使用Timer移动画布:
DispatcherTimer dt = new DispatcherTimer(); //global
public void Ahead(int pix)
{
var movx = 0;
var movy = 0;
dt.Interval = TimeSpan.FromMilliseconds(5);
dt.Tick += new EventHandler((object sender, EventArgs e) =>
{
if (movx >= pix || movy >= pix)
{
dt.Stop();
return;
}
Bot.Body.RenderTransform = new TranslateTransform(movx++, movy++);
});
dt.Start();
}
public void TurnLeft(double deg)
{
var currAngle = 0;
dt.Interval = TimeSpan.FromMilliseconds(5);
dt.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
if (currAngle <= (deg - (deg * 2)))
{
dt.Stop();
}
Bot.Body.RenderTransform = new RotateTransform(currAngle--, BodyCenter.X, BodyCenter.Y);
});
dt.Start();
}
现在,从另一个库中,这些方法被调用如下:
public void run()
{
Ahead(200);
TurnLeft(90);
}
当然,我希望这些动画能够在另一个之后发生,但正在发生的事情是dt.Tick
的{{1}}事件处理程序在第二种方法时被覆盖(在本例中为{ {1}})被调用,因此,只有第二种方法按原样执行。
我需要创建某种队列,允许我将方法推送到该队列,以便DispatchTimer
(TurnLeft(90)
计时器)逐个执行它们...按顺序他们在'队列'
我可以这样做吗?我是在正确的轨道上,还是完全偏离正轨?
答案 0 :(得分:1)
当您在Dispatcher上调用Invoke()或BeginInvoke()时,操作将排队并在与Dispatcher关联的线程空闲时运行。因此,不要使用Tick事件,而是使用带有Timespan的Dispatcher.Invoke的重载。
答案 1 :(得分:1)
我自己解决了这个问题。我所做的是创建类型为Queue
的全局Delegate
,而不是直接执行方法,我将它们添加到此队列。
然后我会在构造函数中有一个单独的线程,它将逐个出列方法并执行它们:
Queue<TimerDelegate> eventQueue = new Queue<TimerDelegate>();
public Vehicle(IVehicle veh, Canvas arena, Dispatcher battleArenaDispatcher)
{
DispatcherTimer actionTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(100) };
actionTimer.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
if (IsActionRunning || eventQueue.Count == 0)
{
return;
}
eventQueue.Dequeue().Invoke(new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(5) });
});
actionTimer.Start();
}
public void TurnRight(double deg)
{
eventQueue.Enqueue((TimerDelegate)delegate(DispatcherTimer dt)
{
IsActionRunning = true;
var currAngle = 0;
dt.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
lock (threadLocker)
{
if (currAngle >= deg)
{
IsActionRunning = false;
dt.Stop();
}
Rotator_Body.Angle++;
currAngle++;
}
});
dt.Start();
});
}