Born Again
Born Again

Reputation: 2179

Thread.join() not working

This is the comple java class (GFXSurface). Inside this class, a second class is defined,

public class GFXSurface extends Activity implements OnTouchListener {

    AnotherSurface ourSurfaceView;
    float x, y;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        ourSurfaceView = new AnotherSurface(this);
        ourSurfaceView.setOnTouchListener(this);
        x = 0;
        y = 0;
        setContentView(ourSurfaceView);
    }
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        ourSurfaceView.ourPause();
    }
    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        ourSurfaceView.ourResume();
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        x = event.getX();
        y = event.getY();
        return true;  
    }

    /*------------------------Class within a class-------------------------------*/

    public class AnotherSurface extends SurfaceView implements Runnable {

        SurfaceHolder ourHolder;
        Thread ourThread = null;
        boolean isRunning;

        public AnotherSurface(Context context) {
            // TODO Auto-generated constructor stub
            super(context); //not auto-generated; set it up manually
            isRunning = false;
            ourHolder = getHolder();    
        }

        public void ourPause(){
            isRunning = false;
            while(true){
                try {
                    ourThread.join();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;
            }
            ourThread = null;
        }

        public void ourResume(){
            isRunning = true;
            ourThread = new Thread(this);
            ourThread.start();
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true){
                if(!ourHolder.getSurface().isValid())
                    continue;

                Canvas canvas = ourHolder.lockCanvas();
                canvas.drawRGB(255, 0, 0);
                if(x!=0 && y!=0){
                    Bitmap ourBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.green_ball);
                    canvas.drawBitmap(ourBitmap, x-(ourBitmap.getWidth()/2), y-(ourBitmap.getHeight()/2), null);
                }
                ourHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
}

Now, when I start the activity, it works as is required, it creates a bitmap at the place where the screen is clicked (centered at the point of click). The problem it gives is that, when I press the back key on my phone, the app stops responding and the phone gives an option to force shut the app. I think the it has got to do something with the "ourThread" thread not being joined properly.

Any idea where the problem lies? Thanks.


EDIT: I have actually found where I was going wrong. In the while loop:

while(true){
        if(!ourHolder.getSurface().isValid())
            continue;

        Canvas canvas = ourHolder.lockCanvas();
        canvas.drawRGB(255, 0, 0);
        if(x!=0 && y!=0){
            Bitmap ourBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.green_ball);
            canvas.drawBitmap(ourBitmap, x-(ourBitmap.getWidth()/2), y-(ourBitmap.getHeight()/2), null);
        }

I just changed "true" to "isRunning". And now the thread does end, and thus, the activity closes on pressing the back button. Thanks all for your valuable suggestions.

Upvotes: 2

Views: 8527

Answers (1)

Gray
Gray

Reputation: 116908

The problem is that, "ourThread" never stops when it is joined.

You have to realize that calling ourThread.join() only waits for the thread to finish -- it won't stop the thread. Your ourThread may be hung for some reason. A thread dump will show where it is running. Maybe it is stuck in a loop? Maybe it is waiting on a network connection?

If the join() returns successfully, by definition, the thread was was joined is no longer running. So the thread calling ourThread.join() will wait until the ourThread thread has completed.

If the thread is no longer running then maybe there are other threads running keeping your application open? A thread dump will show you what other non-daemon threads are still around. They will need to terminate before your application will stop.

In looking at your thread code, I don't see any way for you to exit the infinite loop unless a RuntimeException is thrown. When does the thread stop working? Did you mean to do a break; instead of a continue;?

while(true){
    if(!ourHolder.getSurface().isValid())
        continue; // should this be a break?
    Canvas canvas = ourHolder.lockCanvas();
    canvas.drawRGB(255, 0, 0);
    ourHolder.unlockCanvasAndPost(canvas);
}

Now that you've added more code, you need to make isRunning be volatile so that multiple threads can update it and see the updates and you should change the while loop in your run() method to be:

private volatile boolean isRunning;
...
while(!isRunning){

Upvotes: 2

Related Questions