# TimerTask - Task stoppen - timer.cancel() funktioniert nicht



## armer Tropf (16. Mai 2007)

Hallo zusammen,

ich habe folgendes Problem. Ich führe einen Task aus, in dem z.B. GPS Daten ausgelesen werden. Die Ausführung startet, wenn ein bestimmter Befehl über den Com-Port gesendet wird. Das funktioniert so weit auch. Ich möchte nun aber genau diesen Task auch wieder stoppen, wenn ein bestimmter Befehl gesendet wird ("StopGPS"). Ich habe versucht dies mit timer.cancel() zu realisieren, aber leider funktioniert das nicht. Vielleicht kann mir jemand weiterhelfen oder hat Tipps für mich, was da nicht funktioniert. Ich hatte timer.cancel() auch schon in der run-Methode stehen, aber dann stoppt der Task direkt nach einmaligem auslesen von GPS-Daten. Ich möchte aber, dass der Task so lange ausgeführt wird bis ein Befehl gesendet wird. Wäre für jede Hilfe sehr dankbar.

Anbei ein bissel Code aus meinem Programm: 


```
// Hier lese ich den Befehl ein und bestimme was passieren soll
public static void getCommand(StringBuffer command) {
        ...
        Timer timer = new Timer();
        if (command.toString().equalsIgnoreCase("startGPS")) {
	      getRMCData(timer);				
        } else if (command.toString().equalsIgnoreCase("stopGPS")) {
	      timer.cancel();
        }
        ...
}

// Task starten und alle 300ms ausführen...
public static void getRMCData(Timer timer) {
	timer.schedule(new TaskRMC(), 1, 300);
        ...
}


// GPS Daten holen...
public class TaskRMC extends TimerTask {
        public void run() {
              String replyRMC = GPSInterface.getInstance().requestRMC();
              ...
        }
}
```

Gruß Stephie


----------



## madboy (16. Mai 2007)

Hi Stephi,

Das Problem wird sein, dass du eine andere Instanz von Timer canceln willst als die, in der die TimerTask läuft.


```
// Hier lese ich den Befehl ein und bestimme was passieren soll 
public static void getCommand(StringBuffer command) { 
        ... 
        Timer timer = new Timer();  //<-- Hier wird ein neuer Timer erstellt
        if (command.toString().equalsIgnoreCase("startGPS")) { 
         getRMCData(timer);             
        } else if (command.toString().equalsIgnoreCase("stopGPS")) { 
         timer.cancel();                       //<-- und hier wird der oben neu erstellte Timer gecancelt.
        } 
        ... 
}
```

Vorschlag: 


```
...
private Timer timer = new Timer(); 
...

// Hier lese ich den Befehl ein und bestimme was passieren soll 
public static void getCommand(StringBuffer command) { 
        ... 
        if (command.toString().equalsIgnoreCase("startGPS")) { 
         getRMCData(timer);             
        } else if (command.toString().equalsIgnoreCase("stopGPS")) { 
         timer.cancel();                      
        } 
        ... 
}
```

Damit greifst du immer auf die gleiche Timerinstanz zu.

Gruß,
madboy

EDIT: so weit ich mich erinnere, lässt sich ein einmal gecancelter Timer nicht nochmal verwenden. Verwende lieber "deineTimerTask.cancel()".


----------



## armer Tropf (16. Mai 2007)

Hallo,

danke für deine Antwort.
Ja, auf den Haken bin ich auch grad gestoßen. Ich kann zar damit das Prozedere stoppen, aber wenn ich es wieder starten möchte bekomme ich die Meldung, dass der Timer bereits gestoppt wurde und daher nicht mehr verwendet werden kann :-(

Was meinst du mit "Verwende lieber "deineTimerTask.cancel()"."??

Stephie


----------



## madboy (16. Mai 2007)

Hi,

Du verwendest folgendes, um eine neue Task zum Timer hinzuzufügen:

```
timer.schedule(new TaskRMC(), 1, 300);
```

Speichere die Tasks in einer Liste o.ä. So etwa:


```
...
private HashMap <String, TimerTask> timerTasks = new HashMap <String, TimerTask>();
...

// Task starten und alle 300ms ausführen... 
public static void getRMCData(Timer timer) { 
  TimerTask task = new TaskRMC();
   timer.schedule(task, 1, 300); 

  //id für jede Task festlegen
   timerTasks.put("taskid1", task);
        ... 
}
```

Dann kannst Du jede Task z.B. mit

```
timerTasks.get("taskid1").cancel();
```
 canceln.

Gruß,
madboy


----------



## armer Tropf (16. Mai 2007)

Hallo nochmal,

mit deinem Hinweis habe ich es mit einer Hashtable versucht, da es glaub bei J2ME keine HashMaps gibt?!


```
public static void getRMCData(Timer timer, String command) {
		Hashtable timerTasks = new Hashtable();
		TimerTask taskRMC = new TaskRMC();
		
		if (command.toString().equalsIgnoreCase("startGPS")) {
			timer.schedule(taskRMC, 1, 300);
			timerTasks.put("1", taskRMC);
		} else if (command.toString().equalsIgnoreCase("stopGPS")) {
			timerTasks.remove("1");
			timerTasks.clear();
			
		}
	}
```

Wenn ich nun "stopGPS" als Befehl erhalte springt das Programm zwar in den entsprechenden Abschnitt (habe ich mit System.out.println() getestet ;-) ), aber leider passiert nach timerTasks.remove("1") und timerTasks.clear() nichts.

Sorry, vielleicht sitz ich auf dem Schlauch, aber was ist denn nun wieder falsch?! 

Stephie


----------



## madboy (16. Mai 2007)

Hi,


```
public static void getRMCData(Timer timer, String command) { 
      Hashtable timerTasks = new Hashtable(); 
      TimerTask taskRMC = new TaskRMC(); 
       
      if (command.toString().equalsIgnoreCase("startGPS")) { 
         timer.schedule(taskRMC, 1, 300); 
         timerTasks.put("1", taskRMC); 
      } else if (command.toString().equalsIgnoreCase("stopGPS")) { 
         timerTasks.remove("1"); 
         timerTasks.clear(); 
          
      } 
   }
```
Hier ist das gleiche Problem wie vorher mit dem Timer. Du erstellst eine neue Hashtableinstanz und darin willst du was entfernen, was du vorher in eine andere Instanz gepackt hast.

Das

```
Hashtable timerTasks = new Hashtable();
```
muss ausserhalb der Methode "getRMCData" stehen.

Ausserdem sollte *vor* dem timerTasks.remove()  noch die Task gecancelt werden, also

```
timerTasks.get("1").cancel();
```


----------



## armer Tropf (16. Mai 2007)

Oh sorry, hab die falsche Version gepostet.
Also ich hab die Hashtable und auch den TimerTask außerhalb der getRMCData(), aber es funzt trotzdem nicht.

Und bei der Haschtable gibt es bei mir leider keine cancel(). Ich hab schon gesucht und find auch im Netz immer den Hinweise auf cancel(), aber kann es sein, dass es bei J2ME diese Funktion nicht gibt.
Den eigentlich zeigt Eclipse ja alle Möglichkeiten an?! 
Daher habe ich gehofft, mit remove und clear ist es getan. Aber leider keine Reaktion..mein Task läuft ungestört weiter.


Danke.


----------



## madboy (16. Mai 2007)

> Und bei der Haschtable gibt es bei mir leider keine cancel().


Stimmt. Das cancel() ist nicht von Hashtable sondern von TimerTask.

Du musst also casten, falls aus der Hashtable nur Objekte (Typ Object) rauskommen:

```
...
         Object o = timerTasks.get("1");
         ((TimerTask) o).cancel();
         timerTasks.remove("1"); 
         timerTasks.clear();
...
```

Das 

```
timerTasks.clear();
```
kannst übrigens weg lassen, dazu ist das 
	
	
	
	





```
timerTasks.remove("1");
```
 da.



> Den eigentlich zeigt Eclipse ja alle Möglichkeiten an?!


So weit ich weiß, tut Eclipse das.

Zur Erklärung noch was:
Die Hashtable ist nur dazu da, dass die Instanz von TimerTask (vielmehr TaskRMC) gespeichert wird und du später noch darauf zugreifen kannst. Das ganze ist eigentlich nicht nötig wenn du nur eine TimerTask hast.

Ohne Hashtable würde es dann so ungefähr aussehen:

```
private static TimerTask taskRMC =  null;
     
  public static void getRMCData(Timer timer, String command) { 
       
      if (command.toString().equalsIgnoreCase("startGPS")) { 
         taskRMC = new TaskRMC();
         timer.schedule(taskRMC, 1, 300); 
      } else if (command.toString().equalsIgnoreCase("stopGPS")) { 
          taskRMC.cancel();
      } 
   }
```

Gruß,
madboy


----------



## armer Tropf (16. Mai 2007)

Oh man, ich danke dir.
Ich hatte die ganze Zeit noch folgenden Fehler drin, weswegen es bei mir auch gar nie klappen konnte. Ich hab nicht in der getRMCData()


```
taskRMC = new TaskRMC();
```

gemacht, sondern davor. Somit konnte ich natürlich nach dem canceln keinen neuen Task mehr ausführen.

Vor lauter Wald den Baum net gesehen.


Nochmals danke, war wirklich ne super Unterstützung von dir.

Schönes verlängertes WE.
Stephie


----------

