Question

I'm trying to read bytes from the accessory's InputStream without blocking the thread (if possible).

Typically, I would wrap the read(buffer) call in an if available(), however available() throws an exception (even though read() works fine on the InputStream).

Are there any other solutions that would minimize thread blocking?

EDIT:

I setup AsyncTask to do the reading in the background (though I know I should use a real thread for an extended task), and it works fine-ish.

I guess the real question then is, is there any damage to performance from having a background thread constantly blocked by the 'read' call? There's no effect now, but the application will become pretty intensive soon, and I'd like to at least make the communication as light-weight as possible.

Would a BufferedInputStream reduce the load at all? That has it's own available() method.

Was it helpful?

Solution

In response to your edited question, no, there is no performance penalty from having a background thread blocked on a read() call. Basically it is as if the background thread is sleeping.

However, if you keep spawning background threads, and you keep allowing all of them to sit blocked on read() forever, then you will have a pretty serious memory leak on your hands. It won't degrade performance in terms of speed or anything like that, but it will eventually crash your app.

So yes, it is important to make sure that your background threads eventually terminate (or at least to guarantee that your code isn't going to keep trying to add new ones if the existing ones do not terminate).

This should handle the original issue:

public interface StreamDataHandler {
    public void handleData(byte[] buffer, int numBytes);
    public void readFailedWithError(Exception ex);
}

public class DataReader extends Thread {
    private StreamDataHandler handler;
    private InputStream input;

    public DataReader(InputStream in, StreamDataHandler handler) {
        super();
        this.input = in;
        this.handler = handler;
    }

    @Override
    public void run() {
        int numRead = 0;
        byte[] buffer = new byte[1024];
        try {
            while ((numRead = input.read(buffer)) != -1) {
                if (this.handler != null && numRead > 0) {
                    this.handler.handleData(buffer, numRead);
                }
            }
        }
        catch (Exception e) {
            if (this.handler != null) {
                this.handler.readFailedWithError(e);
            }
        }
    }
}

OTHER TIPS

You could attempt to use a Runnable or a AsyncTask to get around any thread blocking issues.

Runnable

AsyncTask

Alternatively you could look into why that exception is being thrown. You could catch the exception, then have a TimerTask call 'available()' repeatedly until it succeeds.

TimerTask

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top