简体   繁体   中英

NSOperationQueue blocking unrelated NSOperationQueue?

I'm loading an image in the background using NSOperation and NSOperationQueue (for a 2d game).

To understand how NSOperations behaves, I've tried adding the following unrelated NSOperationQueue / NSOperation (I call -startNewEndlessBackgroundTask way before starting any image loading):

static int stop = NO;
static int c = 1000;
-(void)takeTime {
    stop = NO;
    while (!stop) {
        for (int i = 0; i < 10000; i++) {
            c += 1;
        }
        c = c;
    }
}
-(void)stopBackgroundTask {
    stop = YES;
}
-(void)startNewEndlessBackgroundTask {
    //[self performSelectorInBackground:@selector(takeTime) withObject:nil];
    NSOperationQueue* queue = [[NSOperationQueue alloc] init];
    [queue addOperationWithBlock:^{
         [self takeTime];
    }];
}

This completely blocks my other NSOperationQueue for image loading on an iPhone4. On iPhone4s, it blocks my image loading after 2 calls to startNewEndlessBackgroundTask. Both are running iOS 6.

The main loop of my app is not blocked.

If I instead use performSelectorInBackground to invoke takeTime, everything works fine with no blocking, and the takeTime routine working properly in the background as well.

Why could this be happening, when the two NSOperationQueue's are alloc-init'ted completely separately and have no dependencies? To me, there shouldn't be a difference between using an NSOperationQueue in this simple way, and using performSelectorInBackground, but I guess there is something fundamental that I am misunderstanding?

Not sure about the details, but this is a partial answer for what I now think is happening..

NSOperation uses GCD underneath (at least since the last few versions of OSX and iOS). There are certain global priority queues in GCD.

When there is a task in a higher priority queue, tasks in the lower priority queues are not even started (though tasks in the same global priority queue can start, since despite having "queue" in their name, tasks in a default priority queue can be concurrent).

Since I don't specify any thread priority, I imagine my -takeTime operation was being scheduled on the default priority queue, and my image loading operation was being scheduled on the default low priority queue. This would explain why the -takeTime operation was blocking my image loading.

What this doesn't really explain, is why it would take two -takeTime operations to block my image loading operation on an iPhone 4s, since tasks in low priority queues waiting for tasks in high priority queues isn't mentioned to be contingent on the number of CPU cores - as far as I've seen in the docs.

Apple - Dispatch Queues : "In addition to getting the default concurrent queue, you can also get queues with high- and low-priority levels by passing in the DISPATCH_QUEUE_PRIORITY_HIGH and DISPATCH_QUEUE_PRIORITY_LOW constants to the function instead, or get a background queue by passing the DISPATCH_QUEUE_PRIORITY_BACKGROUND constant. As you might expect, tasks in the high-priority concurrent queue execute before those in the default and low-priority queues. Similarly, tasks in the default queue execute before those in the low-priority queue."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM