1

I am using (and am required to use) a third-party framework to which I do not have source. The third-party framework handles creating an authenticated client/server connection and hands back a pair of open NSStreams. The challenge that I have is the NSStreams are scheduled on the main thread (creating situations where the UI may become unresponsive - which I would like to avoid).

At the point that the streams are handed off from the third party framework, no network traffic is in progress. So, I am wondering if I could just unschedule and reschedule the NSStreams.

Does anyone know if it is possible to unschedule an open NSStream and reschedule it on a different run loop on a different thread? Will that cause problems? Are there any code examples out there?

Thanks in advance!

Aaron

xyzzycoder
  • 1,831
  • 13
  • 19
  • Is it actually scheduling it in the thread or just blocking? If its just blocking, you could use NSInvocationOperation on the function call to get it to not block. – heckman May 24 '12 at 15:07
  • @heckman I'm not sure that I understand your question. I'm receiving an NSInputStream and an NSOutputStream. Both have a status of NSStreamStatusOpen when I receive them. No traffic is on the streams until I start sending something, so they are effectively in stasis. Being on the main thread, they will create blocking situations when the delegate message are received/serviced. – xyzzycoder May 24 '12 at 16:29

1 Answers1

0

If I understand your application correctly, it means that your application receives references to a particular stream, and you are in charge of reading everything on the steams. Reading these streams should be something that you force into the background from your application via a NSThread, NSOperation or other threading mechanism.

Example:

In whatever file your tieing in this NSInputStream:

@property (strong, nonatomic) NSInvocationOperation *parseOp; 

(id)startInputRead:(NSInputStream *)input {
    if([input hasBytesAvailable]) {
        self.parseOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(readAndStoreInput:) object:inputStream];

    }

Where your reader is something like:

(void)readAndStoreInput:(NSInputSteam*) input{
     //process your input steam into your system in the background

}

This is a short example of just how you would do this for the input side. You could also queue up work for the output steam in a similar fashion. This should make everything run concurrently and your app stay responsive.

heckman
  • 499
  • 3
  • 8
  • 1
    Hi. But Apple's docs say this "You should never attempt to access a scheduled stream from a thread different than the one owning the stream’s run loop." https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html#//apple_ref/doc/uid/20002273-BCIJHAGD – xyzzycoder May 24 '12 at 20:42
  • I think that the code in this response would be thread agnostic about where the NSStream was read from. Apple's docs seem pretty clear that this is a no-no. – xyzzycoder May 24 '12 at 20:43
  • @xyzzycoder are you performing the scheduleInRun loop? There is no reason that you couldn't put all of the code in listing 1 in your background subprocess – heckman May 24 '12 at 20:46
  • The stream is coming to me in a status of NSStreamStatusOpen. The stream construction process is alloc/init, set delegate, schedule in run loop, then open. So, the scheduling is set when I receive it. – xyzzycoder May 24 '12 at 21:02
  • With that in mind then, can you just read/write it quick and then queue up the processing of that information in the background? You would then not block your main thread to process it, but would be able to correctly maintain the scheduling loop. – heckman May 24 '12 at 21:31
  • I guess, that sounds like you would either need to break it up and make it a periodic read/write, or find a way to initialize your entire 3rd party library in a background thread. Without knowing more about what your doing thats all I can come up with! – heckman May 24 '12 at 23:02