我正在为使用WPF的计算机科学项目创建一个节奏游戏(不像吉他英雄 - 但带有箭头的下降游戏),并且出现了一些性能问题。我使用了很多DispatcherTimers,这会减慢应用程序的运行速度并导致它冻结。为了解决这个问题,我找到了一个answer,建议使用System.Threading.Timers。调度员没有出现在课堂上 - 使用System.Threading.Timer
我明白,通过使用这个,我为这些定时器创建了新线程,这些定时器允许它们在同一时间运行而不会减慢应用程序的速度。
我定时器创建方法是这样的:
private void SetTimers()
{
_arrowKeytimer = new Timer(new TimerCallback(Timer_ArrowTick), null, 0, 775);
//_timerHealth = new Timer(new TimerCallback(Timer_HealthTick), null, 0, 775);
_MediaTimer = new Timer(new TimerCallback(Timer_MediaTick), null, 0, 775);
_leftFall = new Timer(new TimerCallback(LeftArrowFall), null, 0, 775);
_rightFall = new Timer(new TimerCallback(RightArrowFall), null, 0, 775);
_upFall = new Timer(new TimerCallback(UpArrowFall), null, 0, 775);
_downFall = new Timer(new TimerCallback(DownArrowFall), null, 0, 775);
_spawner = new Timer(new TimerCallback(Timer_SpawnTick), null, 0, 775);
}
有一次,我已经改变了从旧蜱我所有的方法,我跑的程序。瞬间我得到'不能从另一个线程访问对象。'例外。
望着这answer,我用的是造成异常打勾Dispatcher.Invoke方法:
private void DownArrowFall(object state)
{
this.Dispatcher.Invoke((Action)(() => //Added the Invoke thing that the answer said to do
{
double y;
for (int z = 0; z < TheDirector.DownArrowList.Count; z++) // Before I would get the exception on this line
{
if ((string)TheDirector.DownArrowList[z].Tag == "Spawned")
{
y = Canvas.GetTop(TheDirector.DownArrowList[z]);
y += FallSpan;
Canvas.SetTop(TheDirector.DownArrowList[z], y);
}
}
double position = Canvas.GetTop(TheDirector.DownArrowList[0]);
if (position >= 700)
{
TheDirector.RemoveDownArrow();
}
}));
}
我再次运行程序,并最终抛出同样的异常在我的画法在我的LeftArrow类中(在屏幕上绘制向下的左箭头)。然而,并称调用没有工作:
public void Draw()
{
this.Dispatcher.Invoke((Action)(() => //Apparently 'Dispatcher' doesn't exist
{
for (int x = 0; x < _arrows.Count; x++)
{
if ((string)_arrows[x].Tag == "NotSpawned")
{
_arrows[x].Tag = "Spawned";
_canvas.Children.Add(_arrows[x]);
Canvas.SetLeft(_arrows[x], Coordinates.LeftArrowX);
Canvas.SetTop(_arrows[x], Coordinates.Y);
break;
}
}
}));
}
我不知道我在做什么 - 我已经检查了所有关于这个问题的答案。我知道我的_arrows列表是由主线程创建的,这就是我得到这些例外的原因,但我不知道该如何处理它们。
谢谢。
关于我的更多信息:
每个ArrowFall定时器通过所有箭头的屏幕上的列表中进行搜索(取决于它是什么列表中,有四个,1左箭头,第2右箭头等等),并在将新位置设置到画布之前在其Y坐标中添加一定量。
所以基本上,我只需要两个对象 - 我添加到的画布和其中一个列表。其他线程只需要访问他们自己的列表和画布。
注意:列表存储在名为Director的类(在此例中命名为实例是TheDirector)中,矩形列表作为属性。这些属性返回由每个箭头的类填充的列表 - 类'RightArrow','LeftArrow'等。
当你有8个完全不同步的线程在你的游戏逻辑上运行时,你仍然无法解决* real *问题。划痕这种方法。 Google为下一个“wpf游戏循环”。 –
这是与每个计时器有自己的线程,我收集? –
我检查了游戏循环 - 并且它不以我想要的方式工作。比赛比以前更慢。具有不同持续时间的定时器是否有帮助?如果没有,那么上述需要工作。我总是可以切断几个定时器来处理更少的线程。 –