【问题标题】:Pausing a Thread - Activity pause timeout for HistoryRecord暂停线程 - HistoryRecord 的活动暂停超时
【发布时间】:2010-06-30 13:43:44
【问题描述】:

我正在尝试在 Android 中编写游戏引擎,但我对线程不太熟悉。

我的线程有一个属性 mSurfaceHolder,它保存了我将要绘制的表面。我的线程的 run() 方法如下所示:

public void run() {
    // We're running now
    setState(STATE_RUNNING);

    // Keep looping while the game is running or paused
    while (mState == STATE_RUNNING || mState == STATE_PAUSED) {
        synchronized (mSurfaceHolder) {
            // If the game is running, update physics etc.
            if (mState == STATE_RUNNING) {
                updateGame();
            }
            // Draw the game even if it's paused
            drawGame();
        }
    }
}

STATE_RUNNING 表示 Activity 处于前台并且游戏应该正在运行时的状态。 STATE_PAUSED 表示另一个活动进入前台时的状态。我不完全确定为什么我还需要在暂停时继续画画,但这似乎是我从LunarLander example 收集到的。

我希望在我查看活动时,游戏会更新和绘制(我使用 LogCat 进行测试)。然后当我返回主屏幕或顶部出现另一个活动时,它就会绘制。

确实在我观看活动时进行绘制和更新,因此游戏循环本身可以工作。但是当我离开活动时,它没有任何效果。这是从 Activity 的 onPause() 调用的线程的 pause() 方法:

public void pause() {
    Log.d("Game","Here");
    synchronized (mSurfaceHolder) {
        Log.d("Game","There");
        // If the thread is running, pause it
        if (mState == STATE_RUNNING) {
            setState(STATE_PAUSED);
        }
    }
}

如您所见,为了测试此方法,我记录了一些消息。现在,当我离开活动时,我发现“这里”已记录,但“那里”没有。现在,由于我对线程的了解有限(我几乎不知道synchronized 实际做了什么),我相信这会发生,因为我的线程无法与表面保持器同步。但我不知道为什么它不同步。离开活动几秒钟后,我在 LogCat 中看到以下警告:

Activity pause timeout for HistoryRecord

知道为什么会发生这种情况吗?如果我再次尝试启动 Activity 没有问题,线程会保持原样运行。

非常感谢。

编辑:刚刚发现了一些别的东西。如果我在启动活动后大约一秒钟内离开活动,线程就会暂停。然后它将在同一任务仍在运行时再次恢复并暂停,完全没有问题。我不知道为什么它会在短时间内起作用,但如果我放得太久,它就不会了。

编辑 2:好的……我修好了。但我不认为我应该做我已经做过的事情。我基本上已经从 pause() 和 setState() 方法(由 pause() 使用)中删除了与 mSurfaceHolder 的任何同步。不,它按预期工作,但我认为同步是有原因的。

也许对我来说最好的问题是: 何时应该使用同步块将线程与对象同步?而在这种情况下,与SurfaceHolder同步的目的是什么?

【问题讨论】:

    标签: android multithreading android-activity game-loop


    【解决方案1】:

    Java 中的synchronize 关键字确保两个线程不能同时接触同一个对象,从而防止出现竞争条件。换句话说,它实现了锁定。

    您很可能在这里遇到了死锁。另一个线程可能正在使用mSurfaceHolder,因此持有该对象的锁。 synchronized (mSurfaceHolder) 中的代码将阻塞,直到其他线程完成,这显然不会发生。

    但是,由于您实际上并未以任何方式修改mSurfaceHolder,因此没有理由对其进行锁定。您唯一需要记住的是 mState 可能会在 pause() 被调用和您更新它的值之间被读取。如果这是个问题,请在 mState 上同步。

    【讨论】:

    • 谢谢,这真的帮助我理解了这种情况。我也围绕这个主题做了一些阅读。
    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-20
    • 1970-01-01
    • 2016-03-26
    • 2013-02-10
    • 1970-01-01
    相关资源
    最近更新 更多