Приостановка потока - Тайм-аут паузы активности для HistoryRecord - PullRequest
2 голосов
/ 30 июня 2010

Я пытаюсь написать игровой движок для 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 представляет состояние, когда другая деятельность вышла на первый план.Я не совсем уверен, почему мне все еще нужно рисовать, пока оно приостановлено, но я, похоже, понял из примера LunarLander .

Я надеюсь, что пока яСмотрю на активность, игра обновится и нарисует (что я тестирую с помощью LogCat).А потом, когда я возвращаюсь на домашний экран или на экране появляется другое действие, оно просто нарисует.Сам игровой цикл работает.Но когда я оставляю активность, это не имеет никакого эффекта.Вот метод потока pause (), который вызывается из функции 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);
        }
    }
}

Как видите, для проверки этого метода я записал в журнал некоторые сообщения.Теперь, когда я ухожу, я нахожу, что «Здесь» зарегистрировано, а «Там» нет.Теперь, с моим ограниченным знанием потоков (я едва знаю, что на самом деле делает synchronized), я верю, что это произойдет, потому что мой поток не может быть синхронизирован с держателем поверхности.Но я не знаю, ПОЧЕМУ это не синхронизируется.Через несколько секунд после того, как я покинул игру, я вижу следующее предупреждение в LogCat:

Activity pause timeout for HistoryRecord

Есть идеи, почему это может произойти?Нет проблем, если я снова попытаюсь запустить упражнение, поток просто продолжит работать, как и было.

Большое спасибо.

РЕДАКТИРОВАТЬ : Просто обнаружил что-то еще,Поток приостанавливается, если я оставляю активность примерно через секунду после ее запуска.И затем он возобновится и снова остановится без проблем, пока та же задача еще выполняется.Я понятия не имею, почему в течение короткого периода времени это будет работать, но если я оставлю это слишком долго, это не будет.

РЕДАКТИРОВАТЬ 2 : Хорошо ... Я исправил это,Но я не думаю, что я должен делать то, что я сделал.Я в основном удалил любую синхронизацию с mSurfaceHolder из методов pause () и setState () (которая используется pause ()).Нет, это работает так, как и должно, но я думаю, что причина синхронизации есть.

Возможно, лучший вопрос, который мне нужно задать, это: КОГДА следует синхронизировать поток с объектом с помощьюсинхронизированный блок?И в этом случае, какова цель синхронизации с SurfaceHolder?

1 Ответ

3 голосов
/ 01 июля 2010

Ключевое слово synchronize в Java гарантирует, что два потока не могут одновременно касаться одного и того же объекта, предотвращая состояние гонки.Другими словами, он реализует блокировку.

Скорее всего, здесь вы столкнулись с тупиком.Другой поток, вероятно, использует mSurfaceHolder и поэтому удерживает блокировку для этого объекта.Ваш код в synchronized (mSurfaceHolder) будет блокироваться до тех пор, пока этот другой поток не завершится, что, по-видимому, не происходит.

Однако, поскольку вы на самом деле не изменяете mSurfaceHolder, нет причин удерживать блокировкув теме.Единственное, что вы должны иметь в виду, это то, что mState может быть прочитан между временем вызова pause() и обновлением его значения.Если это проблема, выполните синхронизацию на mState.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...