1

我正在为游戏制作一个内存读取器,并且我在后台运行了一个几乎无限的线程来检查玩家的位置,然后使用 Invoke() 将其显示在标签上。我只会发布有问题的功能。每 10 毫秒在同一个线程上调用一次。

Invoke((MethodInvoker)delegate
        {
            lblCoords.Text = "Player Coordinates: < " + (int)x + ", " + (int)y + ", " + (int)z + " >";
        });

代码运行大约 20 分钟后,会崩溃并抛出与该函数相关的 StackOverflowException。为什么会发生,我该如何阻止它?显然我可以停止使用标签来显示它,尽管了解它为什么会发生以供将来参考会更有用。

所以这是线程方法,有人提到它是一次创建的多个对象,我将假设是这样,因为它是调用 UpdateThread() 的无限循环......如果这有一个 while 循环而不是调用自身?

private void UpdateThread()
    {
        if (!running) return;

        ReadPos();

        Thread.Sleep(100);
        UpdateThread();
    }

private void ReadPos()
    {
        int pointerAddress = Memory.HexToDec(MemoryOffsets.PlayerPosAddress);

        byte[] xVal = memory.PointerRead((IntPtr)pointerAddress, 4, MemoryOffsets.PlayerX);
        byte[] yVal = memory.PointerRead((IntPtr)pointerAddress, 4, MemoryOffsets.PlayerY);
        byte[] zVal = memory.PointerRead((IntPtr)pointerAddress, 4, MemoryOffsets.PlayerZ);

        float x = BitConverter.ToSingle(xVal, 0);
        float y = BitConverter.ToSingle(yVal, 0);
        float z = BitConverter.ToSingle(zVal, 0);

        Invoke((MethodInvoker)delegate
        {
            lblCoords.Text = "Player Coordinates: < " + (int)x + ", " + (int)y + ", " + (int)z + " >";
        });
    }

程序向我显示的错误指向 Invoke 方法,这就是为什么我认为它只是导致它的原因。由于发生异常大约需要 20 分钟,因此我无法获得太多有关它的信息。

4

2 回答 2

0

这应该有一个while循环而不是调用自己吗?是的,无论如何。

Sanly C# 不会为此代码生成尾调用,这意味着它将堆栈调用,UpdateThread直到调用堆栈已满。这是导致StackOverflowException.

所以,你会实现这样的事情:

private void UpdateThread()
{
    while (running) //I'm assuming running is a volatile variable
    {
       ReadPos();
       Thread.Sleep(100);
    }
}

注意:最好让运行不稳定,因为它将由另一个线程设置(我想)。

您还可以考虑将执行发布到线程循环或类似的调度机制,而不是使用专用线程,在这方面,进行测试以查看最有效的方法。


要考虑的另一件事是让您的委托对象保持活动状态,这将减少垃圾收集器的压力(因为您当前创建了太多短期对象),但这不是StackOverflowException.

于 2013-11-01T22:13:54.443 回答
0

是的,您应该改用循环。

您正在使用递归进行循环,并且由于循环没有合理的限制,它将用调用帧填满堆栈。

只需在方法内部循环:

private void UpdateThread()
{
    while (running) {
      ReadPos();
      Thread.Sleep(100);
    }
}
于 2013-11-01T22:19:14.473 回答