views:

66

answers:

1

I have a NSOperation that downloads some data using NSURLConnection, it looks somewhat like this:

....
- (void)main
{
....
   while (!self.isCancelled && !self.isLoaded)
   {
      [NSRunloop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NDate distantFutute]];
   }
....
}

The problem is that from time to time connection hangs and since there are no other sources firing, the loop keeps running forever, leaving no chance to cancel the operation. Since there is a limit for 1 operation in my operation queue, everything is pretty much stuck.

The question is what would be the best solution to this problem.

  1. Instead of distantFuture use a smaller time period like half a second. (Will probably eat extra cpu cycles)
  2. Try to store a reference to running thread in ivar and tickle run loop via perform selector on thread in operartion's cancel method. (Can result in situation when we queue a selector on a run loop which has already exited and will no longer run, which results in a leak as far as i know)

Or maybe there is another way?

+1  A: 

Here's a hybrid approach:

  • Run the run loop for the longest time you're willing to wait for the data to load (beforeDate:[NSDate dateWithTimeIntervalSinceNow:kConnectionMaxWaitSeconds]).
  • Create a version 0 run loop source (CFRunLoopSourceCreate) and add it to the run loop before you start waiting.
  • Have the -cancel method signal that source (CFRunLoopSourceSignal) and wake up (CFRunLoopWakeUp) the run loop.
Jeremy W. Sherman
Very interesting approach. Will definetly try that, thank you.
stackzerad
Just one more question. What is creating and signaling source for? why can't I just call CFRunLoopWakeUp?
stackzerad
Perhaps it is unnecessary. Try using just `CFRunLoopWakeUp()` and see.
Jeremy W. Sherman