导致IndexOutOfRangeException的计时器
本文关键字:计时器 IndexOutOfRangeException 导致 | 更新日期: 2023-09-27 18:26:46
我有一些类似下面代码的代码。这有点复杂,但本质上,在我的游戏中,在看似随机的时候,我会得到一个IndexOutOfRange
异常。
当我阅读更多详细信息时,它说异常发生在参数"index"上(我没有一个名称,所以我认为它可能来自List<Rectangle>
)。
void Update()
{
CurrentIndex++
if(CurrentIndex > EndFrame)
{
CurrentIndex = StartFrame;
}
}
public override Rectangle GetSize(Vector2 position)
{
//Exception occurs here
return new Rectangle(
(int)(position.X + MaxCharacterSize.X - AnimationList[CurrentFrame].BoundingBox.Width),
(int)(position.Y + MaxCharacterSize.Y - AnimationList[CurrentFrame].BoundingBox.Height),
AnimationList[CurrentFrame].BoundingBox.Width,
AnimationList[CurrentFrame].BoundingBox.Height);
}
为什么这会引发异常?它甚至很难调试,因为它似乎是随机发生的。Update()
只被Timer.Elapsed
事件调用,这会是什么原因吗?
我将永远感谢能够回答这个问题的人。
没有一个好的代码示例很难说。但是,您的Timer.Elapsed事件很可能是在处理GUI的线程之外的线程上引发的。因此,您有一个竞争条件,在该条件下,计时器可以增加索引,但在该线程暂时挂起并且GUI线程尝试使用(现在无效)索引之前,还没有将其包裹起来。
解决方法之一:
void Update()
{
int newIndex = CurrentIndex + 1;
if(newIndex > EndFrame)
{
newIndex = StartFrame;
}
CurrentIndex = newIndex;
}
既然如此,(再次)如果没有更好的代码示例,就不可能看到您可能还有哪些其他线程错误。以上假设CurrentIndex是"易失性"的,并且在其他线程运行时,EndFrame和StartFrame不会更改。
异常是因为CurrentIndex
的值超出了AnimationList
列表的末尾。
如果没有完整的代码,这很难说,但我会考虑两件事:
-
确保
EndFrame
没有关闭一(即,确保它没有初始化为AnimationList的长度,因为如果是,那么AnimationList[EndFrame]无效,并将抛出该异常) -
确保
Update()
例程不能在与GetSize()
方法不同的线程中启动。如果是(并且必须是),则需要进行一些同步,以防止在CurrentIndex
递增和到达列表末尾的检查之间调用GetSize()
。