Newsgroup: it.comp.java
Titolo: DataInputStream inchiudibile

Salve a tutti,
ho questo problema.... ho uno stream DataInputStream in attesa di un byte da 
un canale dove nn puň ricevere niente per questo motivo nn riesco a 
chiuderlo.
code:------------------------------------------------------------------------------public 
void run(){
              try {
                  while(!done){
                     if(!pause){
                        byte byteReceived = dis.readByte();
                        ...
------------------------------------------------------------------------------
questo č il metodo di una classe che implementa Runnable.
Sto usando J2ME quindi nn posso usare metodi della classe Thread come 
destroy() o interrupt().
Qualcuno ha qualche consiglio?

 Qualcuno ha qualche consiglio?
Non ho ancora messo mano su J2ME, ma teoricamente potresti provare il 
sistema del WatchDog, vale a dire un secondo Thread parallelo che ha facoltà 
di chiudere lo stream che è rimasto inattivo per troppo tempo.
Guarda questa classe e vedi se può esserti utile (l'ho scritta al volo 
proprio ora):
public class WatchDog {
   private Thread wdthread=null;
   private volatile boolean timeToStop=false;
   private boolean running=false;
   private Runnable timeoutTask=null;
   private int timeout=0;
   private boolean checked=false;
 
   public WatchDog(int timeout, Runnable timeoutTask) {
      this.thimeoutTask=timeoutTask;
      this.timeout=timeout;
   }
 
   public void start() {
      if (wdthread!=null) return;
      wdthread=new Thread(new Runnable() {public void run() {go();}});
      wdthread.start();
   }
   public void stop() {
      if (wdthread==null) return;
      timeToStop=true;
      wdthread.interrupt();
      wdthread=null;
   }
   public boolean isRunning() {return runnning;}
 
   public void check() {checked=true;}
   private void go() {
      running=true;
      while (!timeToStop) {
         try {thread.Sleep(timeout);} catch (InterruptedException ex) {}
         if ((!timeToStop) && (!checked)) {
            timeoutTask.run();
            timeToStop=true;
         } else checked=false;
      }
      running=false;
   }
}
Il lavoro di questa classe è semplice: ne crei un'istanza prima di iniziare 
il loop di lettura con un timeout di... mettiamo 5 secondi (5000ms). Ogni 
volta che il tuo loop è in grado di leggere un byte, richiami il metodo 
check() sul WatchDog. Se tra due letture passano più di 5sec, lo Sleep del 
WatchDog scade, permettendogli di richiamare il task che avrai passato in 
fase di costruzione, che dovrà soltanto chiudere forzatamente lo Stream. 
Questo, di contro, sbloccherà la readByte con un'eccezione del tipo "Stream 
closed" che dovrai catturare e gestire.
Nel tuo caso questo diventa (riprendo il codice che hai postato):
------------------------------------------------------------------
public void run(){
   WatchDog wd=new WatchDog(5000, new Runnable() {
      public void run() {
         try {
            dis.close();
         } catch (IOException ex) {} //o quello che sia in J2ME
      }
   });
   try {
      while(!done){
         wd.start();
         if(!pause){
            byte byteReceived = dis.readByte();
            wd.check();
.....
------------------------------------------------------------------
Spero possa esserti utile ;)
-- 
Fermiamo Scientology prima che sia troppo tardi!!!
http://xenu.com-it.net
  ---  
http://xenu.freewinds.cx
(per rispondere personalmente leva IlDitoDalCulo)

 Qualcuno ha qualche consiglio?
Non ho ancora messo mano su J2ME, ma teoricamente potresti provare il 
sistema del WatchDog, vale a dire un secondo Thread parallelo che ha facoltà 
di chiudere lo stream che è rimasto inattivo per troppo tempo.
Guarda questa classe e vedi se può esserti utile (l'ho scritta al volo 
proprio ora):
public class WatchDog {
   private Thread wdthread=null;
   private volatile boolean timeToStop=false;
   private boolean running=false;
   private Runnable timeoutTask=null;
   private int timeout=0;
   private boolean checked=false;
 
   public WatchDog(int timeout, Runnable timeoutTask) {
      this.thimeoutTask=timeoutTask;
      this.timeout=timeout;
   }
 
   public void start() {
      if (wdthread!=null) return;
      wdthread=new Thread(new Runnable() {public void run() {go();}});
      wdthread.start();
   }
   public void stop() {
      if (wdthread==null) return;
      timeToStop=true;
      wdthread.interrupt();
      wdthread=null;
   }
   public boolean isRunning() {return running;}
 
   public void check() {checked=true;}




   try {
      while(!done){
         wd.start();
         if(!pause){
            byte byteReceived = dis.readByte();


 Qualcuno ha qualche consiglio?
Non ho ancora messo mano su J2ME, ma teoricamente potresti provare il 
sistema del WatchDog, vale a dire un secondo Thread parallelo che ha facoltà 
di chiudere lo stream che è rimasto inattivo per troppo tempo.
Guarda questa classe e vedi se può esserti utile (l'ho scritta al volo 
proprio ora):
public class WatchDog {
   private Thread wdthread=null;
   private volatile boolean timeToStop=false;
   private boolean running=false;
   private Runnable timeoutTask=null;
   private int timeout=0;
   private boolean checked=false;
   private Object lock=new Object();
 
   public WatchDog(int timeout, Runnable timeoutTask) {
      this.thimeoutTask=timeoutTask;
      this.timeout=timeout;
   }
 
   public void start() {
      if (wdthread!=null) return;
      wdthread=new Thread(new Runnable() {public void run() {go();}});
      wdthread.start();
   }
   public void stop() {
      if (wdthread==null) return;
      timeToStop=true;
      wdthread.interrupt();
      wdthread=null;
   }
   public boolean isRunning() {return running;}
 
   public void check() {sychronized (lock) {checked=true;}}
   private void go() {
      running=true;
      while (!timeToStop) {
         try {thread.Sleep(timeout);} catch (InterruptedException ex) {}
         synchronized (lock) {




   try {
      while(!done){
         wd.start();
         if(!pause){
            byte byteReceived = dis.readByte();


   }
Purtroppo nn so come fermare il thread che gestisce lo stream in entrata se 
nn c'è niente nel canale di trasmissione. 



Ho dato un'occhiata alla documentazione, ho visto che è possibile scambiare
l'uso di sleep/interrupt con una coppia wait/notify di Object. In questo
caso puoi reimplementare la classe WatchDog in questo modo:
public class WatchDog {
   private Thread wdthread=null;
   private volatile boolean timeToStop=false;
   private boolean running=false;
   private Runnable timeoutTask=null;
   private int timeout=0;
   private boolean checked=false;
   private Object lock=new Object();
   public WatchDog(int timeout, Runnable timeoutTask) {
      this.thimeoutTask=timeoutTask;
      this.timeout=timeout;
   }
 
   public void start() {
      if (wdthread!=null) return;
      wdthread=new Thread(new Runnable() {public void run() {go();}});
      wdthread.start();
   }
   public void stop() {
      if (wdthread==null) return;
      timeToStop=true;
      synchronized (lock) {lock.notify();}
      wdthread=null;
   }
   public boolean isRunning() {return running;}
 
   public void check() {sychronized (lock) {checked=true;}}
   private void go() {
      running=true;
      while (!timeToStop) {
         synchronized (lock) {      
            try {lock.wait(timeout);} catch (InterruptedException ex) {}
            if ((!timeToStop) && (!checked)) {
               timeoutTask.run();
               timeToStop=true;
            } else checked=false;
         }
      }
      running=false;
   }
}
Comunque bastava studiare per bene la documentazione... e dire che J2ME non
l'ho ancora mai usato...


Prova ad usare il metodo available della classe DataInputStream...vedi
guida:
public int available()
              throws IOException
    Returns the number of bytes that can be read from this input stream without blocking.
    This method simply performs in.available() and returns the result.
    Overrides:
        available in class InputStream
    Returns:
        the number of bytes that can be read from the input stream without blocking. 
    Throws:
        IOException - if an I/O error occurs.
    See Also:
Ciao, Davide


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com
 - The #1 Newsgroup Service in the World!
-----==  Over 100,000 Newsgroups - 19 Different Servers! =-----

Ok ma tu cosě nn chiudi lo stream.....
Faccio un codice d'esempio
import java.io.*;
public class Prova extends Runnable{
    DataInputStream dis;
    Thread thisThread
    boolean done;
    public Prova(){
        dis = new DataInputStream(/*InputStream*/);
    }
    public void go(){
        thisThread = new Thread(this);
        thisThread.start();
    }
    public void run(){
        while(!done){
            byte byteReceived = dis.readByte();
            System.out.println("Ricevuto byte: " + byteReceived);
        }
        dis.close();
    }
    public void stop(){
        this.done = true;
        try{
            dis.close();
        }catch(Exception e){
            System.out.println("Catturata Eccezione alla chiusura dello 
stream: " + e);
            e.printStackTrace();
        }
        thisThread = null;
    }
}
Secondo te questo codice si blocca se chiamo il metodo stop() ??
La risposta č no perche se lo stream č vuoto il metodo run si blocca alla 
riga
byte byteReceived = dis.readByte();
quindi prima di impostare un timeout sulla ricezione di un byte devo 
riuscire a chiudere lo stream. Se risolvo questo risolvo tutto.

Grazie davide,
non so come io possa aver ignorato questo metodo.
Provo subito. 

 riuscire a chiudere lo stream. Se risolvo questo risolvo tutto.
Puoi sempre chiudere uno stream da un thread diverso da quello che ha
chiamato readByte() (ed è esattamente questo il compito del WatchDog). Il
risultato è che il readByte() si interrompe e lancia un'eccezione (che
dovrai catturare).
Usando la funzione available() (come proposto da davide), dovresti
richiamarla in continuazione per vedere se è possibile leggere dei byte
dallo stream senza bloccare il flusso... e ti assicuro (per esperienza
personale) che un sistema del genere funziona, ma ammazza le prestazioni del
tuo programma:
- in un normale PC, il consumo di tempo CPU sale al 100% e le altre
applicazioni in esecuzione rallentano paurosamente
- in un cellulare (o PDA), ad impantanarsi sono gli altri thread della tua
applicazione, inoltre il sottosistema di controllo della KVM potrebbe non
gradire questo consumo, fino ad arrivare alla chiusura forzata della tua
applicazione
Lasciare invece che il thread si lettura di "fermi" su readByte() è la
soluzione ideale perchè la lettura delle informazioni dallo stream (quando
disponibili) viene effettuata da codice "nativo" della piattaforma, che *sa*
come mettersi in attesa senza piantare la piattaforma stessa.
poi, fai te...


 poi, fai te...
Beh fino ad ora questa è l'unica soluzione. Pensavo di bloccare il Thread in 
qualche modo ma nn so come... 

Pardon ho capito ora cosa intendevi dire ^_^
Beh effettivamente nn hai tutti i torti.... 

Ok mi scuso con tutti per questi messaggi a cascata (nn sono abituato ai 
NG).
Quindi se modifico il metodo stop() della precedente classe prova in:
public void stop(){
        new Thread(new Runnable(){
            public void run(){
                done = true;
                try{
                    dis.close();
                }catch(Exception e){
                    System.out.println("Catturata Eccezione alla chiusura 
dello stream: " + e);
                    e.printStackTrace();
                }
                thisThread = null;
            }
        }).start();
    }
dovrebbe funzionare giusto?? 



Adesso ci stiamo confondendo in due mi sa...
Allora, vista la tua classe per intero, è evidente che tutta la lavorazione
del flusso è già fatta da un thread DIVERSO da quello che crea l'oggetto
Prova, quindi sei già in una condizione di sicurezza. Io pensavo che ti
fossi "impantanato" sul blocco del thread provocato da readByte, ma per come
hai strutturato la classe sei già al sicuro. La classe che ti avevo proposto
di aggiungere (la WatchDog di qualche post fa) serve solo per implementare
un controllo di timeout di lettura.
Quindi il tuo metodo stop() va benissimo senza dover inglobare il tutto in
un nuovo thread, dato che il thread che chiama stop() è gia diverso da
quello bloccato sul readByte()
....
   public void stop() {
      done=true;
      try {
         dis.close();
      } catch (IOException ex) {
         ex.printStackTrace();
      }
      thisThread=null;
   }
....
Logicamente avrai del codice da qualche parte nel tuo programma che fa
........
   Prova objProva=new Prova();
   objProva.go(); //Qui inizia la lettura asincrona dello stream
   //ma il metodo go() ritorna subito dopo aver avviato il thread
   //quindi QUESTO flusso di istruzioni non è bloccato
 
   //...fai qualche altra cosa nel frattempo...
 
   objProva.stop(); //è ora di chiudere!
........
Fai sempre attenzione a mettere qualche sistema di controllo, ad esempio
puoi impedire che il metodo go() crei un altro thread se ce n'è uno in
esecuzione (in un PC una condizione del genere darebbe dei problemi nel
momento di uscire dall'applicazione).


 -- 
Beh si quella classe è stata creata con il semplice scopo di riassumere il
mio problema....ovviamente nella classe autentica faccio tutti i controlli
adeguati.
Ci tenevo a ringraziarti per il tempo che mi hai concesso e per aver
"risolto" il mio problema.