views:

695

answers:

5

My code needs to run all networking routines in a separate NSThread. I have got a library, which I pass a callback routine for communication:

my thread code
    library
        my callback (networking)
    library
my thread code

My callback routine must POST some data to an HTTP server (NSURLConnection), wait for the answer (start a NSRunLoop?), then return to the library.
The library then processes the data. After the library returns to my thread, I can then post a notification to the main thread which handles drawing and user input.

Is there any sample code covering how to use NSURLConnection in a NSThread?

A: 

To answer your mini-question "start an NSRunLoop?":

I'm not sure I understand, but it sounds like you are saying your pseudocode above is all being executed on a secondary thread (i.e., not the main event processing thread). If that's the case, there probably isn't any point in creating an NSRunLoop, because you can't do any useful work while waiting for the HTTP server to respond. Just let the thread block.

benzado
+1  A: 

If you need to block until you've done the work and you're already on a separate thread, you could use +[NSURLConnection sendSynchronousRequest:returningResponse:error:]. It's a bit blunt though, so if you need more control you'll have to switch to an asynchronous NSURLRequest with delegate methods (i.e. callbacks) scheduled in the current NSRunLoop. In that case, one approach might be to let your delegate flag when it's done, and allow the run loop to process events until either the flag is set or a timeout is exceeded.

Graham Lee
A: 

NSURLConnection can be used synchronously, via its asynchronous delegate methods, in a background thread (e.g. NSThread or NSOperation). However, it does require knowledge of how NSRunLoop works.

There is a blog post w/ sample code and an explanation, here: http://stackq.com/blog/?p=56

The sample code downloads an image, but I've used the concept to make sophisticated POST calls to a REST API.

-Kelvin

Kelvin
A: 

Any particular reason you're using threads? Unless you're opening a lot of connections, NSRunLoop on the main thread should be good enough. If you need to do blocking work in response, create your thread then.

Peter Hosey
+1  A: 

Kelvin's link is dead, here's a bit of code that does what you are asking for (meant to be run in a method called by [NSThread detachNewThreadSelector:toTarget:WithObject:]). Note that the connection basically starts working as soo as you enter the run loop, and that "terminateRunLoop" is meant to be a BOOL set to NO on start and set to YES when the connection finishes loading or has an error.

Why would you want to do this instead of a blocking synchronous request? One reason is that you may want to be able to cancel a long-running connection properly, even if you do not have a lot of them. Also I have seen the UI get hung up a bit if you start having a number of async requests going on in the main run loop.

NSURLConnection *connection = [[NSURLConnection connectionWithRequest:request delegate:self] retain];
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
while(!terminateRunLoop) 
{
    if ( ![[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
                                   beforeDate:[NSDate distantFuture]]) 
        {  break; }

        [pool drain];
    }
    [pool release];
}
Kendall Helmstetter Gelner