Re: How do I use NSStream with dispatch queues?
Re: How do I use NSStream with dispatch queues?
- Subject: Re: How do I use NSStream with dispatch queues?
- From: Steve Sisak <email@hidden>
- Date: Tue, 20 Mar 2012 22:25:34 -0400
Title: Re: How do I use NSStream with dispatch
queues?
Hi Jens,
At 9:49 AM -0700 3/20/12, Jens Alfke wrote:
On Mar 19, 2012, at 8:06 PM, Raffi
Khatchadourian wrote:
There's another method named
-performSelectorOnThread, which lets you run code in an arbitrary
loop.
Where? It doesn't show up in the
documentation. I've looked for something like that before but
haven't found it.
It's in NSThread.h -- looks like it showed up in 10.5
@interface
NSObject (NSThreadPerformAdditions)
[snip]
#if MAC_OS_X_VERSION_10_5 <=
MAC_OS_X_VERSION_MAX_ALLOWED
- (void)performSelector:(SEL)aSelector
onThread:(NSThread *)thr withObject:(id)arg
waitUntilDone:(BOOL)wait modes:(NSArray *)array;
- (void)performSelector:(SEL)aSelector
onThread:(NSThread *)thr withObject:(id)arg
waitUntilDone:(BOOL)wait;
// equivalent to the first method
with kCFRunLoopCommonModes
- (void)performSelectorInBackground:(SEL)aSelector
withObject:(id)arg;
#endif
@end
I've noticed that Xcode doesn't like to suggest methods which are
in categories, however.
(I constantly have to search for this or type from memory -- I
use it a LOT).
At 11:59 AM -0700 3/19/12, Jens Alfke wrote:
I want to fix the threading of some
increasingly-complex network code I'm writing[1]. Currently it all
ends up running on the internal NSURLConnection thread (ick!) because
it's invoked by an NSURLProtocol instance. I want to move it all to
a dispatch queue. But I'm finding out that it's hard to wean
existing code off of runloop-based asynchrony.
Are you sure that this is the right tool for the job? If the API
you're working from is runLoop based, what does this buy you (besides
a warm feeling of being "modern")?
My current sticking point is NSStream.
Even though my code is all HTTP-based, I have to use NSStream to be
able to stream large HTTP bodies (using the
NSURLRequest.HTTPBodyStream property.) And unlike NSURLConnection,
NSStream doesn't have a way to hook its delegate up to a dispatch
queue, only to a runloop.
Why not create a utility thread/runLoop for your own
purposes?
But the alternative - not using
dispatch queues - still seems really primitive.
This sounds a tad religious --
"primitive"/"modern" -- I'd probably use a hybrid
of NSOperationQueue and runLoop.
I'd have to spawn my own NSThread,
start up a runloop on it, implement a custom thread-safe queue to hold
request objects of some sort, and write some CFRunLoop glue to twiddle
a runloop source so I can wake up the thread when a request is
posted.
This is as simple as [self detachNewThreadWithSelector:] and in
your selector method caching the current thread and runLoop in
instance variables, then enter a runloop (preferably with at least one
source so it doesn't exit immediately).
Then, when ever you want to do something in a synchronized
manner, call performSelector:onThread:withObject:waitUntilDone: using
your utility thread.
I did it once before in 2005 and it was
surprisingly hard to get right.
If it's helpful, I can send you a utility class I wrote which
launches a utility thread on demand and takes a delegate which it
calls at key points (before the runLoop, after the runLoop, etc.) I've
been meaning to post it in a collection of utilities for general
use.
It really seemed like GCD had fixed all
of this, but now it looks to me like GCD support is still kind of
half-baked, even several years after it showed up in 10.6. Or am I
missing something?
Given that you need your responses serialized, not sure if GCD
buys you nything here.
Also, since NSURLProtocol is a glorified delegate to the URL
loading system, I'm not sure that running on its threads poses any
problem -- am I missing something?
-Steve
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden