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 09:53:42 -0500
On Aug 30, 2009, at 9:09 AM, Steven Degutis wrote:
Unfortunately, the code I wrote completely broke yesterday when I
upgraded
to Snow Leopard (fortunately I hadn't published it yet for that same
reason)
and it was narrowed down to the NSOperation subclass not getting any
of
NSURLConnection's delegate methods at all. In fact, it seemed that the
object wasn't even getting any messages from
-performSelector:withObject:afterDelay: either, which made me wonder
whether
the NSRunLoop of the current NSThread was borked, or if the NSThread
itself
was in fact not intact.
Interestingly, it still worked fine when the NSOperation object was
run with
-start, it only failed when run by being added to an NSOperationQueue.
In 10.6, NSOperationQueue ignores the -isConcurrent property of the
operations and always invokes -start on one of its work threads. This
may have contributed to your problem.
That said, I don't think it's ever been a safe assumption that the
thread on which either -start or -main is invoked has a run loop
that's regularly serviced. If you need the run loop to be run, you
should run it yourself. However, you should probably reconsider
whether you need to be using a secondary thread, at all. An API which
relies on the run loop, like NSURLConnection, is typically already
asynchronous (ignoring for the moment the
+sendSynchronousRequest:returningResponse:error: method). That is,
you can set it up to work on the main thread without blocking it.
A middle ground on 10.6 might be to schedule your operation on +
[NSOperationQueue mainQueue]. Then, its -start will be guaranteed to
be invoked on the main thread. In that case, you should implement the
operation as concurrent. Your -start override should not block while
the operation runs to completion. It should set things going and then
return immediately. Naturally, this requires the very asynchronous
nature of NSURLConnection that I mention above in order to work, which
is why wrapping it up as an operation is largely unnecessary. It does
let you integrate with other operations via the dependency mechanism,
though.
So after more researching of NSOperationQueue's documentation,
specifically
under "Avoid Per-Thread Storage" section of the "Operation Queues"
guide, it
states the following:
"If an operation queue provides a thread for you, you should
consider that
thread to be owned by the queue and not to be touched by your
operation.
Specifically, you should never associate any data with a thread that
you do
not create yourself or manage. The threads managed by an operation
queue
come and go depending on the needs of the system and your application.
Therefore, passing data between operations using per-thread storage is
unreliable and likely to fail."
It seems to be that this exactly describes what is happening when
NSURLConnection is run asynchronously; it tries to use the thread it's
current in and its runloop, even though it created neither, since
NSOperationQueue did.
First of all, am I reading and interpreting this correctly? I could be
mistaken on what this means, as I'm no expert to threads and runloops.
You are basically interpreting it correctly, yes. I would nitpick
with your claim that it happens "when NSURLConnection is run
asynchronously". It happens when NSURLConnection is run in a thread
and that thread's run loop is not guaranteed to be serviced (a.k.a.
run).
Secondly, if so, would it be unwise to set up a thread and runloop
specifically for the NSURLConnection itself?
That would also work, but, again, the NSURLConnection is inherently an
asynchronous API which can be run on the main thread (and main
thread's run loop) without causing trouble. Spinning off your own
thread to just sit in its run loop is unnecessary.
The primary benefit NSURLConnection would get from running async
inside an NSOperation subclass is that it will be more easily
cancelable
I don't understand this claim. NSURLConnection is just about as
easily cancelable as is possible. You just invoke its -cancel
method. It seems to me to be more easily cancelable than if it is
wrapped in an NSOperation subclass.
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