The EASession documentation states that you need to configure the streams by assigning it a delegate which handles the stream events and schedule it in a run loop.
Using a run loop enables you to drive the streams without worrying about threads. For example, if you write into the output stream via the outputStream
property, there's very likely an internal input stream (bound to the public visible output stream) which is used by the EASession
object to obtain the bytes written. This internal input stream (which is not visible) may also use the same run loop as the publicly provided output stream outputStream
.
Don't mismatch the internal input stream with the public input stream! So basically, there are two public streams and two internal streams. Each public stream has an associated pendant internally: a input stream has a bound output stream, and an output stream has a bound input stream.
You can however, avoid using a run loop for your (output) stream: you just need to guarantee that the write:maxLength:
method is executed on a private thread, which is not used by the internal streams by EASession
.
You can get your private thread just by utilizing dispatch. You may try the code below:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[outputStream open];
const char* data = ...;
int dataLength = ...;
while (dataLength && !isCancelled) {
int written = [outputStream write:(const uint8_t*)data maxLength:1];
if (written > 0) {
dataLength -= written;
data += written;
}
else if (written < 0 )
{
// error occurred
break;
}
}
[outputStream close];
});
Note: this will block the thread if a previous call to write:maxLength:
returned zero and if there is still data to write. Thus, the internal streams must not use the same thread, otherwise you get a dead lock.
When the thread is blocked, it becomes difficult to cancel the block. Perhaps, you should try a run loop approach.