导致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事件调用,这会是什么原因吗?

我将永远感谢能够回答这个问题的人。

导致IndexOutOfRangeException的计时器

没有一个好的代码示例很难说。但是,您的Timer.Elapsed事件很可能是在处理GUI的线程之外的线程上引发的。因此,您有一个竞争条件,在该条件下,计时器可以增加索引,但在该线程暂时挂起并且GUI线程尝试使用(现在无效)索引之前,还没有将其包裹起来。

解决方法之一:

void Update()
{
    int newIndex = CurrentIndex + 1;
    if(newIndex > EndFrame)
    {
        newIndex = StartFrame;
    }
    CurrentIndex = newIndex;
}

既然如此,(再次)如果没有更好的代码示例,就不可能看到您可能还有哪些其他线程错误。以上假设CurrentIndex是"易失性"的,并且在其他线程运行时,EndFrame和StartFrame不会更改。

异常是因为CurrentIndex的值超出了AnimationList列表的末尾。

如果没有完整的代码,这很难说,但我会考虑两件事:

  1. 确保EndFrame没有关闭一(即,确保它没有初始化为AnimationList的长度,因为如果是,那么AnimationList[EndFrame]无效,并将抛出该异常)

  2. 确保Update()例程不能在与GetSize()方法不同的线程中启动。如果是(并且必须是),则需要进行一些同步,以防止在CurrentIndex递增和到达列表末尾的检查之间调用GetSize()