我正在使用WPF为计算机科学项目创建一个节奏游戏(不像吉他英雄那样下降的游戏 - 但带箭头)并且遇到了一些性能问题。我使用了很多DispatcherTimers,这会降低应用程序的速度并使其冻结。为了解决这个问题,我找到了answer,建议使用System.Threading.Timers。
据我所知,通过使用这个,我为这些计时器创建了新的线程,允许它们同时运行,而不会使应用程序的速度降低到可怕的速度。
我的计时器创建方法是这样的:
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,右箭头为第二等)并向其Y添加一定数量在将新位置设置到画布之前进行坐标。
所以基本上,我只是拿两个对象 - 我要添加的画布和其中一个列表。其他线程只需要访问自己的列表和画布。
注意:列表存储在名为Director的类中(在本例中,命名实例是TheDirector),矩形列表作为属性。这些属性返回列表,这些列表由每个箭头的类填充 - Class'RightArrow','LeftArrow'等。
答案 0 :(得分:0)
最后,我通过采用了很多'ArrowFall'方法并将它们全部合二为一,取出了几个计时器并使我的代码更有效率。到那时,调度员使用较少的计时器,我没有错误。由于我不知道究竟是什么原因引起了问题,我想我最终还是以某种方式解决了这个问题。