views:

41

answers:

1

I guess my question stems from ignorance on how network communication is done on different threads on the iOS platform. I have a TcpConnection class which is a wrapper for input and output streams to a printer. the Open call looks like this:

    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef) ipAddress, port, &readStream, &writeStream);      
    self.myInputStream = (NSInputStream*)readStream;
    self.myOutputStream = (NSOutputStream*)writeStream;

    CFRelease(readStream);
    CFRelease(writeStream);

    [self.myInputStream setProperty:(id)kCFBooleanTrue forKey:(NSString *)kCFStreamPropertyShouldCloseNativeSocket];
    [self.myInputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [self.myInputStream open];

    [self.myOutputStream setProperty:(id)kCFBooleanTrue forKey:(NSString *)kCFStreamPropertyShouldCloseNativeSocket];
    [self.myOutputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [self.myOutputStream open];

The problem is with the [NSRunLoop currentRunLoop] call. When i create this TcpConnection object in a thread which is not the main thread (by using detachNewThreadSelector), I can only communicate with that connection on that thread. If I try to go back to the main thread, or pass it to another thread, I can't get any data back.

If, however, I schedule the input/output streams in the mainRunLoop it works fine. But that scares the pants off of me. I don't know what that will do. Does that mean all stream comm is done on the main thread? Are there any other performance issues? I haven't found any examples where network communications is scheduled on the mainRunLoop; does that mean I shouldn't do it? Am I using threads incorrectly when I try to talk to my TcpConnection from multiple threads?

I read the Threading Programming Guide but it doesn't seem to address this issue. Any help would be appreciated

+1  A: 

By scheduling on the main run loop, you are telling the streams to perform their delegate callbacks on the main thread. This may or may not be an issue, depending on how your stream callbacks behave.

I would say that trying to pass your connection objects between threads is a design smell. What I would recommend would be to have a single, long-lived connection thread which runs its own run loop. Schedule your streams on that thread's run loop, then pass messages between it and other threads to shuffle data onto or off of the network. This will keep your network communication nicely localized to a single thread/run loop.

Jason Foreman