Domanda

Sto cercando di scrivere un motore di gioco in Android, ma non ho molta dimestichezza con le discussioni.

Il mio thread ha un attributo, mSurfaceHolder, che detiene la superficie che sarò disegno da. Il metodo run () per il mio aspetto di filo in questo modo:

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 rappresenta lo stato in cui l'attività è in primo piano e il gioco dovrebbe essere in esecuzione. STATE_PAUSED rappresenta lo stato in cui un'altra attività è venuto in primo piano. Io non sono del tutto sicuro perché ho bisogno di disegnare ancora mentre è in pausa, ma è quello che mi sembra di aver raccolto dal LunarLander esempio .

Quello che sto sperando è che mentre sto guardando l'attività, il gioco aggiornerà e disegnare (che prova utilizzando LogCat). E poi, quando torno alla schermata iniziale o di un'altra attività appare sopra le righe, sarà solo disegnare.

Beh, ha disegnare e aggiornamento mentre sto guardando l'attività, in modo che il ciclo di gioco in sé funziona. Ma quando lascio l'attività, non ha alcun effetto. Ecco pausa del filo () metodo che viene chiamato da onPause della attività ():

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

Come si può vedere, per testare questo metodo che ho registrato alcuni messaggi. Ora quello che trovo quando lascio l'attività è che "qui" è registrato, ma "là" non lo è. Ora con la mia limitata conoscenza delle discussioni (non so proprio che cosa realmente fa synchronized), credo che questo accadrà perché il mio thread non può ottenere sincronizzato con il supporto di superficie. Ma io non so perché non si sincronizza. Pochi secondi dopo ho lasciato l'attività, vedo il seguente avviso in LogCat:

Activity pause timeout for HistoryRecord

Qualsiasi idea del perché questo sarebbe accaduto? Non ci sono problemi se provo a ricominciare l'attività, il thread solo continua a funzionare come prima.

Grazie molto mucho.

Modifica : appena scoperto qualcos'altro. Il filo ferma bene se lascio l'attività all'interno attorno ad un secondo di aver iniziato esso. E poi si riprenderà e la pausa di nuovo senza problemi a tutti mentre lo stesso compito è ancora in esecuzione. Non ho idea del perché per un breve periodo di tempo che funzionerà, ma se lascio troppo a lungo, non lo farà.

Modifica 2 : Va bene ... ho riparato. Ma io non credo di essere dovrebbe di fare quello che ho fatto. Ho praticamente rimosso alcuna sincronizzazione con mSurfaceHolder sia dalla pausa () e la setState () metodi (che viene usato da una pausa ()). Non funziona come si suppone, ma sto pensando la sincronizzazione è lì per un motivo.

Forse la migliore domanda per me da porsi è questa: Quando si deve sincronizzare un filo con un oggetto mediante l'uso di un blocco sincronizzato? E in questo caso, qual è lo scopo della sincronizzazione con il SurfaceHolder?

È stato utile?

Soluzione

La parola chiave synchronize in Java fa in modo che due thread non possono toccare lo stesso oggetto, allo stesso tempo, evitando condizioni di gara. In altre parole, implementa bloccaggio.

Molto probabilmente, si sta incontrando stallo qui. Un altro thread probabilmente sta usando mSurfaceHolder, e pertanto mantiene il blocco per questo oggetto. Il codice in synchronized (mSurfaceHolder) bloccherà fino a che altri Completa filo, che a quanto pare non sta accadendo.

Tuttavia, dal momento che non sta effettivamente modificando mSurfaceHolder in alcun modo, non c'è motivo di tenere un blocco su di esso. L'unica cosa che dovete tenere a mente è che mState potrebbe ottenere leggere tra l'pause() tempo viene chiamato e si aggiorna il suo valore. Se questo è un problema, quindi sincronizzare il mState.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top