暂停线程 - HistoryRecord 的活动暂停超时

发布于 2024-09-08 08:07:09 字数 2025 浏览 7 评论 0原文

我正在尝试用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 表示活动位于前台并且游戏应该运行时的状态。 STATE_PAUSED 表示另一个 Activity 进入前台时的状态。我不完全确定为什么在暂停时我仍然需要绘制,但这似乎是我从 LunarLander 示例

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

好吧,当我观看活动时,它确实进行绘制和更新,因此游戏循环本身可以正常工作。但当我离开活动时,它就没有任何影响。下面是从活动的 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 中看到以下警告:

HistoryRecord 的活动暂停超时

知道为什么会发生这种情况吗?如果我尝试再次启动该活动,则没有问题,线程将继续按原样运行。

非常感谢。

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

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

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

I'm trying to write a game engine in Android, but I don't have much familiarity with threads.

My thread has an attribute, mSurfaceHolder, which holds the surface that I'll be drawing to. The run() method for my thread looks like this:

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 represents the state when the activity is in the foreground and the game should be running.
STATE_PAUSED represents the state when another activity has come into the foreground. I'm not completely sure why I need to still draw while it's paused, but that's what I seem to have gathered from the LunarLander example.

What I'm hoping is that while I'm looking at the activity, the game will update and draw (which I test by using LogCat). And then when I go back to the home screen or another activity appears over the top, it will just draw.

Well it does draw and update while I'm watching the activity, so the game loop itself works. But when I leave the activity, it has no effect. Here is the thread's pause() method that is called from the activity's onPause():

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);
        }
    }
}

As you can see, to test this method I have logged some messages. Now what I find when I leave the activity is that "Here" is logged, but "There" is not. Now with my limited knowledge of threads (I hardly know what synchronized actually does), I believe this will happen because my thread can't get synchronized with the surface holder. But I don't know WHY it doesn't synchronize. A few seconds after I've left the activity, I see the following warning in LogCat:

Activity pause timeout for HistoryRecord

Any idea why this would happen? There are no problems if I try to start the activity again, the thread just keeps running as it was.

Thanks very mucho.

EDIT: Just discovered something else. The thread pauses just fine if I leave the activity within about a second of having started it. And then it will resume and pause again with no problems at all while the same task is still running. I have no idea why for a short period of time it will work, but if I leave it too long, it won't.

EDIT 2: Okay... I fixed it. But I don't think I'm supposed to do what I've done. I've basically removed any synchronization with mSurfaceHolder from both the pause() and the setState() methods (which is used by pause()). No it works as it's supposed to, but I'm thinking the synchronization is there for a reason.

Perhaps the best question for me to ask is this:
WHEN should you synchronize a thread with an object by use of a synchronized block? And in this case, what is the purpose of synchronizing with the SurfaceHolder?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

英雄似剑 2024-09-15 08:07:09

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

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

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

The synchronize keyword in Java makes sure that two threads cannot touch the same object at the same time, preventing race conditions. In other words, it implements locking.

Most likely, you're encountering deadlock here. Another thread is probably using mSurfaceHolder, and is therefore holding the lock for this object. Your code in synchronized (mSurfaceHolder) will block until that other thread completes, which apparently isn't happening.

However, since you're not actually modifying mSurfaceHolder in any way, there's no reason to hold a lock on it. The only thing you have to keep in mind is that mState might get read between the time pause() gets called and you update it's value. If that's a problem, then synchronize on mState.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文