Re: Async NSURLConnection + Concurrent NSOperation = Not possible under Mac OS X 10.6?
Re: Async NSURLConnection + Concurrent NSOperation = Not possible under Mac OS X 10.6?
- Subject: Re: Async NSURLConnection + Concurrent NSOperation = Not possible under Mac OS X 10.6?
- From: Ken Thomases <email@hidden>
- Date: Sun, 30 Aug 2009 12:18:49 -0500
On Aug 30, 2009, at 10:29 AM, Steven Degutis wrote:
Thanks for your detailed response.
You're welcome.
Originally the plan for this class was to
be an NSOperation on the advise of Steve Streza who mentioned that
on Snow
Leopard, NSOperationQueues take advantage of GCD, which would improve
performance.
GCD doesn't magically make things go faster. GCD reduces some of the
overhead of manually creating threads, or passing work items to
existing threads in a custom thread pool. However, the actual
NSURLConnection stuff wouldn't perform any better. Furthermore, you
don't need to do _any_ threading with NSURLConnection, at all, so
there's no way in which using NSOperation or GCD is an improvement
over just using NSURLConnection's asynchronous API on the main thread.
Previously (read: in the source of CocoaREST's class SDNetTask), I
was using
the synchronous method of NSURLConnection to get data back from a
server,
which was done in a non-concurrent NSOperation subclass. This was much
harder to cancel (actually, impossible as far as I know) than the
async
method, and thus I wanted to avoid having non-cancelable operations
simply
so it would not block out an NSOperationQueue when (especially
dependencies
are involved, but also otherwise).
But in order to use NSURLConnection in a concurrent NSOperation, you
have to switch from the synchronous method to the asynchronous
methods. Once you do that part, it is as easily cancelable as can be
without going on to wrap it in an NSOperation.
So, the idea here was basically to create an NSOperation subclass
that could
deal with dependencies, and fit inside an NSOperationQueue (for
plenty of
reasons),
OK. There are some legitimate reasons to want to wrap up uses of
NSURLConnection in an operation to interact with dependencies.
To be honest, I'm not entirely sure what the proper solution here
is. From
what you're saying and from what the docs state, there's no decent
way to
have my cake and eat it too... that is to say, if I use
NSURLConnection
inside an NSOperation, it seems I would need to get rid of its
cancel-ability by using it synchronously, and, furthermore, I
definitely
wouldn't be able to have the class function the same on iPhone,
Leopard, and
Snow Leopard using NSOperationQueue, since they all behave
differently. So,
I either would need to use NSURLConnection in a stand-alone class,
or use it
synchronously inside a non-concurrent NSOperation subclass. (Please
correct
me if I'm wrong!)
As Adam Maxwell said, you can use a non-concurrent operation which
uses the asynchronous NSURLConnection APIs and runs the run loop
itself. Handling cancel may require that you send a message from
whatever thread invoked -cancel to the thread on which your operation
is running, which may be non-trivial. [You might think that -
performSelector:onThread:... makes this trivial, but: 1) you have to
let the canceling thread know which thread to target, and 2) the
canceling thread _must not_ queue up a method invocation to one of
NSOperationQueue's or GCD's threads before your operation is running
on that thread or after your operation has finished running on it.
Consider the race between a -cancel on one thread just as the
operation has completed and stops running its run loop.]
Another approach to consider is to make a concurrent operation which
actually shunts its work to the main thread using -
performSelectorOnMainThread:... So, NSOperationQueue would invoke -
start on whichever thread it likes (you shouldn't rely on it being or
not being anything in particular). -start would perform a selector on
the main thread that creates the NSURLConnection and starts the
download. As a consequence, it will be tied to the main thread's run
loop. As data arrives, NSURLConnection will invoke your delegate
methods on the main thread, too, so they shouldn't block or do long
computations. (If you want to do long computations with the result of
the download, you should queue up a separate operation for that once
the download has completed.) Your operation class will probably want
to respond to -cancel by sending -cancel to the NSURLConnection; this,
too, must be shunted to the main thread.
Basically, this latter approach combines my instinct to just do
asynchronous NSURLConnection work on the main thread, with a thin
wrapper of NSOperation to allow integration with NSOperationQueue.
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden