tags:

views:

190

answers:

4

Mobile app provides the user with the option of downloading the email attachment from remote.Connecting with a remote server and downloading the content is carried out in a separate thread.A dialog is shown to the user with cancel command.Herewith I am providing the pseudo code.

new Thread(new Runnable()
   public void run(){
     try{
     //open connection to remote server
     //get data input stream
     //create byte array of length attachment size
     //show modeless dialog with the message "Downloading..."
     for(int i=0;i<attachmentSize;i++){
       //set the progress indicator of the modeless dialog based upon for iteration
       //read the byte from input stream and store it in byte array
     }
       //open file connection outputstream and store the downloaded content as a file in mobile file system
       //show dialog with the message "attachment successfully downloaded"
      }
      catch(IOException ioe) { }
      catch(Exception ex) { }
   }
).start();

Now I'm in the process of adding cancel command to the dialog with progress indicator. When the user clicks "Cancel" command in mobile, modeless dialog can be disposed by calling dispose() method. How can I abruptly stop the thread which gets the email attachments via streaming? Please do help me to resolve this issue.

A: 

I am not an expert on this so take my suggestion with a grain of salt, as my experience is very limited on Java threads.

You cannot stop a running thread. You can just exit it as soon as possible. So what you could do is to have, for example, a shared flag that you test periodically in the secondary thread. When the main thread sets it in response to a Cancel click, the secondary thread returns.

Stefano Borini
+2  A: 

You can stop it abruptly - but it brings more trouble that it's worth.

The canonical way of doing this is to have a flag which is checked in the Runnable:

public class ClassHoldingRunnable {

    private volatile boolean stopRequested = false;

    public void executeAsync() {

        Runnable r= new Runnable() {

            public void run() {

                while ( !stopRequested ) {
                    // do work
                 }
            }
        }

        new Thread(r).start();
    }

    public void cancel() {
        stopRequested = true;
    }
}

A few notes:

  • it's vital for the stopRequested flag to be either volatile or to have another visibility guarantee ( synchronized, Lock, Atomic ) since it's being accessed by multiple threads;
  • you should check for stopRequested pretty often if it's important for the end user to have a responsive GUI;
Robert Munteanu
A: 

My experience is more in C# but this might still be applicable...

I don't think it's a good idea to find some way of just "killing a thread" any more than you would just delete an object and skip its destructor.

You could tell the thread to commit suicide via an interrupt. You can then either use the thread's interrupted flag as the indicator or, if you have a sleep/wait in there, you could catch an interrupted exception and shut down properly when this is caught (in the finally block). This should provide, more or less, what you're looking for.

Joel Goodwin
A: 

There are several complimentary ways to interrupt a Thread that reads from a Connection.

  • You are probably reading the remote data by looping over a single call to InputStream.read, so you can reuse a single, relatively small, byte[] object. You can check a boolean member variable before each iteration. You don't really need to synchronize around that boolean because it is only supposed to change value once after Thread construction.

  • closing the Connection means that your Thread will throw a IOException when it next tries to access it. A proper JavaME implementation will not make Connection.close() block even if another Thread is reading from the Connection's InputStream.

QuickRecipesOnSymbianOS