多线程奇怪的口吃问题

时间:2011-05-25 12:12:48

标签: c# multithreading xna thread-safety physics

我从上一篇文章修改了我的物理学:Updating physics engine ina separate thread, is this wise?就像这样:

public void PhysicsThread()
{
    int milliseconds = TimeSpan.FromTicks(333333).Milliseconds;
    while(true)
    {
        System.Threading.Thread.Sleep(milliseconds);

        world.Step(milliseconds / 1000.0f);
    }
}

和以前一样,它在自己的线程中运行。我发现了一些奇怪的东西,我不确定我是否完全理解,这有点难以解释所以我录制了它的视频:http://www.youtube.com/watch?v=qFf6oSRfVt8

如果你仔细观察,你可以看到从大炮偶尔发出的物体有时会出现断断续续的情况,并且看起来会向后移动一定距离。这仅适用于快速移动的物体(例如射击的射弹)。

这让我完全感到困惑。我甚至创建了一个系统,我在游戏逻辑线程中缓存物体的位置,这样物理线程可以更新物体位置,它不会影响游戏逻辑读入的位置,直到在内部调用更新函数游戏逻辑线程更新物理主体位置,供游戏逻辑阅读。

任何想法多线程的哪些方面可能会导致此问题?我不认为这是物理引擎在游戏逻辑和绘图过程中更新了身体位置,因为我已经提到过我缓存它并且它在整个过程中保持不变......

2 个答案:

答案 0 :(得分:2)

我的第一个猜测是你可能有一个经典的竞争条件,其中多个线程竞争更新对象的位置而不锁定或排序保证。

您可以查看Wikipedia以了解有关竞争条件,锁定以及多线程/多处理的其他基础知识的更多信息。

如果没有看到更多代码,尤其是更新代码,那么很难说更多。

编辑:您可以做的一件事是在每个循环上存储DateTime.Now,并将其与之前的值进行比较。如果您的时间延迟不一致,您会看到它。

要检查的另一件事是看看你的world.Step()函数执行了多长时间(再次使用DateTime.Now和一些日志记录,或其他)。

如果这两个都表明时间一致,那么我的怀疑将落在物理引擎上。在调用world.Step()之前和之后检查对象的位置,如果你看到任何奇怪的跳转,应该告诉你在哪里看。

答案 1 :(得分:1)

这应该是一个评论,但是发布代码会很困难。如果您正在尝试实时,那么此代码很容易出现时间抖动,因为无法保证Thread.Sleep将在执行时间内休眠。我会用秒表来衡量经过的时间,然后用它来驱动你的世界。

public void PhysicsThread()
{
    int milliseconds = TimeSpan.FromTicks(333333).Milliseconds;
    var stopwatch=System.Diagnostics.Stopwatch.StartNew();

    while(true)
    {
        System.Threading.Thread.Sleep(milliseconds );

        world.Step(stopwatch.ElapsedTicks);
        stopwatch.Restart();
    }
}