2010-06-30 16 views
9

Hier ist meine Situation: Ich baue ein Spiel für Android und meine Spielaktivität besteht aus einem benutzerdefinierten SurfaceView, die einen Thread für die Spiellogik und Rendering hat. Die Architektur ähnelt der LunarLander-Demo von Googles Website."Thread bereits gestartet" beim Fortsetzen der Aktivität

Wenn die Aktivität startet er den Surface erstellt und ruft diese Methode:

@Override 
    public void surfaceCreated(SurfaceHolder holder) 
    { 
     renderThread.start(); 
    } 

Wenn ich die Home-Taste drücken um das Spiel zu beenden, die onPause() -Methode aufgerufen, die surfaceDestroyed() aufruft. In surfaceDestroyed stoppen ich das Spiel Thema durch den Aufruf:

@Override 
    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     synchronized(holder) 
     { 
      renderThread.stop(); 
     } 
    }  

Die App geht in den Hintergrund gut. Dann, wenn ich die App neu starte, indem ich auf das Symbol drücke, bekomme ich eine Meldung "Thread bereits gestartet" im Log zusammen mit einem "Force Close" Popup auf dem Bildschirm. Diese Meldung wird angezeigt, wenn die Aktivität beim Aufruf von start() für den Render-Thread die Methode "sourceCreated" aufruft.

Jetzt habe ich es stundenlang untersucht und kann nicht herausfinden, warum das so ist. Ich glaube, dass mein Thread gestoppt wird, wenn ich die App schließe, also verstehe ich nicht, warum es sagt, dass es bereits begonnen hat.

Antwort

8

Diese Methoden tun nicht, was Sie denken, dass sie tun. Vom API doc:

ist es nie einen Thread mehr als einmal zu starten legal.

Und:

public final void stop() - Veraltete. Diese Methode ist von Natur aus unsicher.

Wenn Sie einen Thread zu unterbrechen wollen, müssen Sie Object.wait() und Objecft.notifyAll() aus dem Thread verwenden.

+1

Hallo, danke für die Antwort. Ich ersetzte stop() durch eine join() in einer while-Schleife. Ich glaube es wartet, bevor der Thread gestoppt wird. Aber ich habe immer noch das gleiche Problem, vermisse ich etwas? Wie für den Beginn des Threads. Ich verstehe, dass der Thread nicht mehr als einmal damit die Fehlermeldung gestartet werden kann. Also denkst du, dass ich diesen Fehler bekomme, nur weil der Thread nicht richtig gestoppt wird? Danke – NioX5199

+1

@ NioX5199: nein, Join() stoppt den Thread auch nicht, es wartet auf es selbst zu beenden. Sie erhalten den Fehler, weil der Thread bereits gestartet ist. Threads * können nicht * gestoppt und neu gestartet werden. Wie ich schrieb: Um einen Thread zu pausieren, bis eine Bedingung erfüllt ist, verwenden Sie Object.wait(). –

+0

Er sollte es wahrscheinlich auch nicht so machen. Den Thread neu zu erstellen ist wahrscheinlich ein besserer Ansatz. – alexanderblom

0

Eine schlechte Lösung, aber es funktioniert ..

public void surfaceCreated(SurfaceHolder holder) { 
     try{ 
     _thread.setRunning(true); 
     _thread.start(); 
     }catch(Exception ex){ 
      _thread = new TutorialThread(getHolder(), this); 
      _thread.start(); 
     } 

    } 

Korrekturen sind herzlich willkommen.

+0

Während dies funktioniert (fsvo), ist es in der Regel keine gute Idee, Probleme Will-Nilly und dann zu versuchen und zu korrigieren. Stattdessen sei * proactive * und gebe Exceptions ihre Bedeutung zurück. –

5

Meiner Meinung nach sollten Sie Ihren Code nicht in eine Unterklasse von Thread packen, wenn Sie den Thread häufig starten und stoppen wollen (die Beispiele machen das, weil er den Code kürzer macht). Verwenden Sie stattdessen eine ausführbare Datei. Auf diese Weise können Sie den alten Thread anhalten und verwerfen, wenn Sie möchten, und ein neues Thread-Objekt erstellen, um das Runnable auszuführen, wenn Sie es erneut starten müssen.

Auch auf Ausnahmen ist schlechte Form. Dies sollte als letzte Möglichkeit verwendet werden, wenn sich der eigene Code unerwartet verhält.

Verwandte Themen